merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 02 May 2016 11:25:32 +0200
changeset 295707 77cead2cd20300623eea2416bc9bce4d5021df09
parent 295534 9c01418829e44b01feaebff72867cd50befc7044 (current diff)
parent 295706 bf82810f72802f6fadbffe23e2f21eb2ddc5a417 (diff)
child 295708 2080375bc69d7dbb001296f145bb0546a732ba2b
child 295796 c0e66d2e692aa0e3f7ebedb19747d1b43996ad08
push id19015
push usercbook@mozilla.com
push dateMon, 02 May 2016 09:39:23 +0000
treeherderfx-team@2080375bc69d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone49.0a1
merge mozilla-inbound to mozilla-central a=merge
browser/base/content/browser-places.js
layout/reftests/backgrounds/background-position-6.html
testing/web-platform/meta/dom/collections/domstringmap-supported-property-names.html.ini
testing/web-platform/meta/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/meta-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/meta-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html.ini
testing/web-platform/meta/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html.ini
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1473,37 +1473,16 @@ var BookmarkingUI = {
   showRecentlyBookmarked() {
     Services.prefs.setBoolPref(this.RECENTLY_BOOKMARKED_PREF, true);
   },
 
   hideRecentlyBookmarked() {
     Services.prefs.setBoolPref(this.RECENTLY_BOOKMARKED_PREF, false);
   },
 
-  /**
-   * Handles star styling based on page proxy state changes.
-   */
-  onPageProxyStateChanged: function BUI_onPageProxyStateChanged(aState) {
-    if (!this._shouldUpdateStarState() || !this.star) {
-      return;
-    }
-
-    if (aState == "invalid") {
-      this.star.setAttribute("disabled", "true");
-      this.broadcaster.setAttribute("stardisabled", "true");
-      this.broadcaster.removeAttribute("starred");
-      this.broadcaster.setAttribute("buttontooltiptext", "");
-    }
-    else {
-      this.star.removeAttribute("disabled");
-      this.broadcaster.removeAttribute("stardisabled");
-      this._updateStar();
-    }
-  },
-
   _updateCustomizationState: function BUI__updateCustomizationState() {
     let placement = CustomizableUI.getPlacementOfWidget(this.BOOKMARK_BUTTON_ID);
     this._currentAreaType = placement && CustomizableUI.getAreaType(placement.area);
   },
 
   _uninitView: function BUI__uninitView() {
     // When an element with a placesView attached is removed and re-inserted,
     // XBL reapplies the binding causing any kind of issues and possible leaks,
@@ -1610,21 +1589,16 @@ var BookmarkingUI = {
     this._uri = gBrowser.currentURI;
     this._itemIds = [];
 
     if (this._pendingStmt) {
       this._pendingStmt.cancel();
       delete this._pendingStmt;
     }
 
-    // We can load about:blank before the actual page, but there is no point in handling that page.
-    if (isBlankPageURL(this._uri.spec)) {
-      return;
-    }
-
     this._pendingStmt = PlacesUtils.asyncGetBookmarkIds(this._uri, (aItemIds, aURI) => {
       // Safety check that the bookmarked URI equals the tracked one.
       if (!aURI.equals(this._uri)) {
         Components.utils.reportError("BookmarkingUI did not receive current URI");
         return;
       }
 
       // It's possible that onItemAdded gets called before the async statement
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2468,17 +2468,16 @@ function UpdateUrlbarSearchSplitterState
 function UpdatePageProxyState()
 {
   if (gURLBar && gURLBar.value != gLastValidURLStr)
     SetPageProxyState("invalid");
 }
 
 function SetPageProxyState(aState)
 {
-  BookmarkingUI.onPageProxyStateChanged(aState);
   if (!gURLBar)
     return;
 
   gURLBar.setAttribute("pageproxystate", aState);
 
   // the page proxy state is set to valid via OnLocationChange, which
   // gets called when we switch tabs.
   if (aState == "valid") {
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -286,17 +286,16 @@ nsContextMenu.prototype = {
   initMiscItems: function CM_initMiscItems() {
     // Use "Bookmark This Link" if on a link.
     let bookmarkPage = document.getElementById("context-bookmarkpage");
     this.showItem(bookmarkPage,
                   !(this.isContentSelected || this.onTextInput || this.onLink ||
                     this.onImage || this.onVideo || this.onAudio || this.onSocial ||
                     this.onCanvas));
     bookmarkPage.setAttribute("tooltiptext", bookmarkPage.getAttribute("buttontooltiptext"));
-    bookmarkPage.disabled = bookmarkPage.hasAttribute("stardisabled");
 
     this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink &&
                                            !this.onSocial) || this.onPlainTextLink);
     this.showItem("context-keywordfield",
                   this.onTextInput && this.onKeywordField);
     this.showItem("frame", this.inFrame);
 
     let showSearchSelect = (this.isTextSelected || this.onLink) && !this.onImage;
--- a/caps/nsIScriptSecurityManager.idl
+++ b/caps/nsIScriptSecurityManager.idl
@@ -21,17 +21,17 @@ class DomainPolicyClone;
 }
 }
 %}
 
 [ptr] native JSContextPtr(JSContext);
 [ptr] native JSObjectPtr(JSObject);
 [ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
 
-[scriptable, uuid(b7ae2310-576e-11e5-a837-0800200c9a66)]
+[scriptable, uuid(da831650-4241-4892-806c-cce8465a2ba8)]
 interface nsIScriptSecurityManager : nsISupports
 {
     /**
      * For each of these hooks returning NS_OK means 'let the action continue'.
      * Returning an error code means 'veto the action'. XPConnect will return
      * false to the js engine if the action is vetoed. The implementor of this
      * interface is responsible for setting a JS exception into the JSContext
      * if that is appropriate.
@@ -238,16 +238,34 @@ interface nsIScriptSecurityManager : nsI
     /**
      * Get the principal for the given channel.  This will typically be the
      * channel owner if there is one, and the codebase principal for the
      * channel's URI otherwise.  aChannel must not be null.
      */
     nsIPrincipal getChannelResultPrincipal(in nsIChannel aChannel);
 
     /**
+     * Temporary API until bug 1220687 is fixed.
+     *
+     * Returns the same value as getChannelResultPrincipal, but ignoring
+     * sandboxing.  Specifically, if sandboxing would have prevented the
+     * channel's triggering principal from being returned by
+     * getChannelResultPrincipal, the triggering principal will be returned
+     * by this method.
+     *
+     * Note that this method only ignores sandboxing of the channel in
+     * question, it does not ignore sandboxing of any channels further up a
+     * document chain.  The triggering principal itself may still be the null
+     * principal due to sandboxing further up a document chain.  In that regard
+     * the ignoring of sandboxing is limited.
+     */
+    [noscript, nostdcall]
+    nsIPrincipal getChannelResultPrincipalIfNotSandboxed(in nsIChannel aChannel);
+
+    /**
      * Get the codebase principal for the channel's URI.
      * aChannel must not be null.
      */
     nsIPrincipal getChannelURIPrincipal(in nsIChannel aChannel);
 
     /**
      * Check whether a given principal is a system principal.  This allows us
      * to avoid handing back the system principal to script while allowing
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -6,16 +6,17 @@
 
 #include "nsScriptSecurityManager.h"
 
 #include "mozilla/ArrayUtils.h"
 
 #include "xpcprivate.h"
 #include "XPCWrapper.h"
 #include "nsIAppsService.h"
+#include "nsIInputStreamChannel.h"
 #include "nsILoadContext.h"
 #include "nsIServiceManager.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIURL.h"
 #include "nsINestedURI.h"
 #include "nspr.h"
 #include "nsJSPrincipals.h"
@@ -324,47 +325,74 @@ nsScriptSecurityManager::AppStatusForPri
  * the load doesn't require sandboxing or inheriting, it will return the same
  * principal as GetChannelURIPrincipal. Namely the principal of the URI
  * that is being loaded.
  */
 NS_IMETHODIMP
 nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
                                                    nsIPrincipal** aPrincipal)
 {
+  return GetChannelResultPrincipal(aChannel, aPrincipal,
+                                   /*aIgnoreSandboxing*/ false);
+}
+
+nsresult
+nsScriptSecurityManager::GetChannelResultPrincipalIfNotSandboxed(nsIChannel* aChannel,
+                                                                 nsIPrincipal** aPrincipal)
+{
+  return GetChannelResultPrincipal(aChannel, aPrincipal,
+                                   /*aIgnoreSandboxing*/ true);
+}
+
+nsresult
+nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
+                                                   nsIPrincipal** aPrincipal,
+                                                   bool aIgnoreSandboxing)
+{
     NS_PRECONDITION(aChannel, "Must have channel!");
     nsCOMPtr<nsISupports> owner;
     aChannel->GetOwner(getter_AddRefs(owner));
     if (owner) {
         CallQueryInterface(owner, aPrincipal);
         if (*aPrincipal) {
             return NS_OK;
         }
     }
 
     // Check whether we have an nsILoadInfo that says what we should do.
     nsCOMPtr<nsILoadInfo> loadInfo;
     aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
     if (loadInfo) {
-        if (loadInfo->GetLoadingSandboxed()) {
+        if (!aIgnoreSandboxing && loadInfo->GetLoadingSandboxed()) {
             RefPtr<nsNullPrincipal> prin;
             if (loadInfo->LoadingPrincipal()) {
               prin =
                 nsNullPrincipal::CreateWithInheritedAttributes(loadInfo->LoadingPrincipal());
             } else {
               NeckoOriginAttributes nAttrs;
               loadInfo->GetOriginAttributes(&nAttrs);
               PrincipalOriginAttributes pAttrs;
               pAttrs.InheritFromNecko(nAttrs);
               prin = nsNullPrincipal::Create(pAttrs);
             }
             prin.forget(aPrincipal);
             return NS_OK;
         }
 
-        if (loadInfo->GetForceInheritPrincipal()) {
+        bool forceInterit = loadInfo->GetForceInheritPrincipal();
+        if (aIgnoreSandboxing && !forceInterit) {
+          // Check if SEC_FORCE_INHERIT_PRINCIPAL was dropped because of
+          // sandboxing:
+          if (loadInfo->GetLoadingSandboxed() &&
+              (loadInfo->GetSecurityFlags() &
+               nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL_WAS_DROPPED)) {
+            forceInterit = true;
+          }
+        }
+        if (forceInterit) {
             NS_ADDREF(*aPrincipal = loadInfo->TriggeringPrincipal());
             return NS_OK;
         }
 
         nsSecurityFlags securityFlags = loadInfo->GetSecurityMode();
         if (securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
             securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
             securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -115,16 +115,20 @@ private:
     ScriptSecurityPrefChanged();
 
     inline void
     AddSitesToFileURIWhitelist(const nsCString& aSiteList);
 
     // If aURI is a moz-extension:// URI, set mAddonId to the associated addon.
     nsresult MaybeSetAddonIdFromURI(mozilla::PrincipalOriginAttributes& aAttrs, nsIURI* aURI);
 
+    nsresult GetChannelResultPrincipal(nsIChannel* aChannel,
+                                       nsIPrincipal** aPrincipal,
+                                       bool aIgnoreSandboxing);
+
     nsCOMPtr<nsIPrincipal> mSystemPrincipal;
     bool mPrefInitialized;
     bool mIsJavaScriptEnabled;
     nsTArray<nsCOMPtr<nsIURI>> mFileURIWhitelist;
 
     // This machinery controls new-style domain policies. The old-style
     // policy machinery will be removed soon.
     nsCOMPtr<nsIDomainPolicy> mDomainPolicy;
--- a/config/stl-headers
+++ b/config/stl-headers
@@ -29,16 +29,17 @@ iterator
 limits
 list
 map
 memory
 ostream
 set
 stack
 string
+type_traits
 utility
 vector
 cassert
 climits
 cmath
 cstdarg
 cstdio
 cstdlib
--- a/config/system-headers
+++ b/config/system-headers
@@ -1109,16 +1109,17 @@ ThreadManagerTests.h
 Threads.h
 time.h
 Timer.h
 tlhelp32.h
 ToolUtils.h
 tr1/functional
 trace.h
 Traps.h
+type_traits
 typeinfo
 types.h
 Types.h
 UAppleEventsMgr.h
 UAttachments.h
 ucontext.h
 uconv.h
 UCursor.h
--- a/devtools/client/animationinspector/test/browser_animation_animated_properties_displayed.js
+++ b/devtools/client/animationinspector/test/browser_animation_animated_properties_displayed.js
@@ -4,17 +4,18 @@
 
 "use strict";
 
 // Test that when an animation is selected, its list of animated properties is
 // displayed below it.
 
 const EXPECTED_PROPERTIES = [
   "background-color",
-  "background-position",
+  "background-position-x",
+  "background-position-y",
   "background-size",
   "border-bottom-left-radius",
   "border-bottom-right-radius",
   "border-top-left-radius",
   "border-top-right-radius",
   "filter",
   "height",
   "transform",
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -3191,19 +3191,17 @@ function parseAttributeValues(attr, doc)
       attributes.push({ name, value });
     } catch (e) {
       // This may throw exceptions on bad input.
       // Prevents InvalidCharacterError - "String contains an invalid
       // character".
     }
   }
 
-  // Attributes return from DOMParser in reverse order from how they are
-  // entered.
-  return attributes.reverse();
+  return attributes;
 }
 
 /**
  * Apply a 'flashed' background and foreground color to elements. Intended
  * to be used with flashElementOff as a way of drawing attention to an element.
  *
  * @param  {Node} backgroundElt
  *         The element to set the highlighted background color on.
--- a/devtools/client/inspector/markup/test/browser_markup_html_edit_03.js
+++ b/devtools/client/inspector/markup/test/browser_markup_html_edit_03.js
@@ -163,17 +163,17 @@ function* testDocumentElement(inspector,
      1, "no extra <body>s have been added");
   is((yield testActor.getProperty("body", "textContent")),
      "Hello", "document.body.textContent has been updated");
 }
 
 function* testDocumentElement2(inspector, testActor) {
   let currentDocElementOuterHMTL = yield testActor.eval(
     "content.document.documentElement.outerHMTL");
-  let docElementHTML = "<html class=\"updated\" id=\"somethingelse\"><head>" +
+  let docElementHTML = "<html id=\"somethingelse\" class=\"updated\"><head>" +
                        "<title>Updated again from document element</title>" +
                        "<script>window.foo=\"bar\";</script></head><body>" +
                        "<p>Hello again</p></body></html>";
   let docElementFront = yield inspector.markup.walker.documentElement();
 
   let onReselected = inspector.markup.once("reselectedonremoved");
   inspector.markup.updateNodeOuterHTML(docElementFront, docElementHTML,
     currentDocElementOuterHMTL);
--- a/devtools/client/shared/test/browser_outputparser.js
+++ b/devtools/client/shared/test/browser_outputparser.js
@@ -46,18 +46,18 @@ function makeColorTest(name, value, segm
     expected: ""
   };
 
   for (let segment of segments) {
     if (typeof (segment) === "string") {
       result.expected += segment;
     } else {
       result.expected += "<span data-color=\"" + segment.name + "\">" +
-        "<span style=\"background-color:" + segment.name +
-        "\" class=\"" + COLOR_TEST_CLASS + "\"></span><span>" +
+        "<span class=\"" + COLOR_TEST_CLASS + "\" style=\"background-color:" +
+        segment.name + "\"></span><span>" +
         segment.name + "</span></span>";
     }
   }
 
   result.desc = "Testing " + name + ": " + value;
 
   return result;
 }
@@ -236,18 +236,18 @@ function testParseURL(doc, parser) {
     });
 
     let target = doc.querySelector("div");
     target.appendChild(frag);
 
     let expectedTrailer = test.expectedTrailer || test.trailer;
 
     let expected = test.leader +
-        "<a href=\"something.jpg\" class=\"test-urlclass\" " +
-        "target=\"_blank\">something.jpg</a>" +
+        "<a target=\"_blank\" class=\"test-urlclass\" " +
+        "href=\"something.jpg\">something.jpg</a>" +
         expectedTrailer;
 
     is(target.innerHTML, expected, test.desc);
 
     target.innerHTML = "";
   }
 }
 
--- a/devtools/client/sourceeditor/test/css_autocompletion_tests.json
+++ b/devtools/client/sourceeditor/test/css_autocompletion_tests.json
@@ -15,18 +15,18 @@
              '-moz-animation-iteration-count', '-moz-animation-name',
              '-moz-animation-play-state', '-moz-animation-timing-function',
              '-moz-appearance']],
   [[12, 20], ['none', 'number-input']],
   [[12, 22], ['none']],
   [[17, 22], ['hsl', 'hsla']],
   [[19, 10], ['background', 'background-attachment', 'background-blend-mode',
               'background-clip', 'background-color', 'background-image',
-              'background-origin', 'background-position', 'background-repeat',
-              'background-size']],
+              'background-origin', 'background-position', 'background-position-x',
+              'background-position-y', 'background-repeat', 'background-size']],
   [[21,  9], ["-moz-calc", "auto", "calc", "inherit", "initial","unset"]],
   [[25, 26], ['.devtools-toolbarbutton > tab',
               '.devtools-toolbarbutton > hbox',
               '.devtools-toolbarbutton > .toolbarbutton-menubutton-button']],
   [[25, 31], ['.devtools-toolbarbutton > hbox.toolbarbutton-menubutton-button']],
   [[29, 20], ['.devtools-menulist:after', '.devtools-menulist:active']],
   [[30, 10], ['#devtools-anotherone', '#devtools-itjustgoeson', '#devtools-menu',
               '#devtools-okstopitnow', '#devtools-toolbarbutton', '#devtools-yetagain']],
--- a/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_01.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_01.js
@@ -14,26 +14,26 @@ thisTestLeaksUncaughtRejectionsAndShould
 // Test the webconsole output for various types of DOM Nodes.
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-console-output-dom-elements.html";
 
 var inputTests = [
   {
     input: "testBodyNode()",
-    output: '<body id="body-id" class="body-class">',
+    output: '<body class="body-class" id="body-id">',
     printOutput: "[object HTMLBodyElement]",
     inspectable: true,
     noClick: true,
     inspectorIcon: true
   },
 
   {
     input: "testDocumentElement()",
-    output: '<html lang="en-US" dir="ltr">',
+    output: '<html dir="ltr" lang="en-US">',
     printOutput: "[object HTMLHtmlElement]",
     inspectable: true,
     noClick: true,
     inspectorIcon: true
   },
 
   {
     input: "testDocument()",
@@ -70,17 +70,17 @@ var inputTests = [
     printOutput: "[object HTMLParagraphElement]",
     inspectable: true,
     noClick: true,
     inspectorIcon: true
   },
 
   {
     input: "testLotsOfAttributes()",
-    output: '<p n="" m="" l="" k="" j="" i="" h="" g="" f="" e="" d="" c="" b="" a="" id="lots-of-attributes">',
+    output: '<p id="lots-of-attributes" a="" b="" c="" d="" e="" f="" g="" h="" i="" j="" k="" l="" m="" n="">',
     printOutput: "[object HTMLParagraphElement]",
     inspectable: true,
     noClick: true,
     inspectorIcon: true
   },
 
   {
     input: "testDocumentFragment()",
--- a/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_02.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_02.js
@@ -18,17 +18,17 @@ const TEST_DATA = [
     // inspector-updated event
     input: "testNode()",
     output: '<p some-attribute="some-value">',
     tagName: "P",
     attrs: [{name: "some-attribute", value: "some-value"}]
   },
   {
     input: "testBodyNode()",
-    output: '<body id="body-id" class="body-class">',
+    output: '<body class="body-class" id="body-id">',
     tagName: "BODY",
     attrs: [
       {
         name: "class", value: "body-class"
       },
       {
         name: "id", value: "body-id"
       }
@@ -37,17 +37,17 @@ const TEST_DATA = [
   {
     input: "testNodeInIframe()",
     output: "<p>",
     tagName: "P",
     attrs: []
   },
   {
     input: "testDocumentElement()",
-    output: '<html lang="en-US" dir="ltr">',
+    output: '<html dir="ltr" lang="en-US">',
     tagName: "HTML",
     attrs: [
       {
         name: "dir",
         value: "ltr"
       },
       {
         name: "lang",
--- a/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_04.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_04.js
@@ -16,25 +16,25 @@ const TEST_DATA = [
     // The first test shouldn't be returning the body element as this is the
     // default selected node, so re-selecting it won't fire the
     // inspector-updated event
     input: "testNode()",
     output: '<p some-attribute="some-value">'
   },
   {
     input: "testBodyNode()",
-    output: '<body id="body-id" class="body-class">'
+    output: '<body class="body-class" id="body-id">'
   },
   {
     input: "testNodeInIframe()",
     output: "<p>"
   },
   {
     input: "testDocumentElement()",
-    output: '<html lang="en-US" dir="ltr">'
+    output: '<html dir="ltr" lang="en-US">'
   }
 ];
 
 const PREF = "devtools.webconsole.persistlog";
 
 function test() {
   Services.prefs.setBoolPref(PREF, true);
   registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
--- a/devtools/server/actors/inspector.js
+++ b/devtools/server/actors/inspector.js
@@ -432,20 +432,17 @@ var NodeActor = exports.NodeActor = prot
     return false;
   },
 
   writeAttrs: function () {
     if (!this.rawNode.attributes) {
       return undefined;
     }
 
-    // The NamedNodeMap implementation in Firefox (returned by
-    // node.attributes) gives attributes in the reverse order compared
-    // to the source file when iterated. So reverse the list here.
-    return [...this.rawNode.attributes].reverse().map(attr => {
+    return [...this.rawNode.attributes].map(attr => {
       return {namespace: attr.namespace, name: attr.name, value: attr.value };
     });
   },
 
   writePseudoClassLocks: function () {
     if (this.rawNode.nodeType !== Ci.nsIDOMNode.ELEMENT_NODE) {
       return undefined;
     }
--- a/devtools/server/tests/mochitest/test_inspector-search.html
+++ b/devtools/server/tests/mochitest/test_inspector-search.html
@@ -151,17 +151,17 @@ window.onload = function() {
         {node: inspectee.querySelectorAll("h2")[1], type: "selector"},
         {node: inspectee.querySelectorAll("h2")[2], type: "selector"},
       ]
     },
     {
       desc: "Search with multiple matches in a single tag expecting a single result",
       search: "💩",
       expected: [
-        {node: inspectee.getElementById("💩"), type: "attributeName"}
+        {node: inspectee.getElementById("💩"), type: "attributeValue"}
       ]
     },
     {
       desc: "Search that has tag and text results",
       search: "h1",
       expected: [
         {node: inspectee.querySelector("h1"), type: "tag"},
         {node: inspectee.querySelector("h1 + p").childNodes[0], type: "text"},
--- a/docshell/test/mochitest.ini
+++ b/docshell/test/mochitest.ini
@@ -65,17 +65,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 support-files = bug530396-noref.sjs bug530396-subframe.html
 [test_bug540462.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug551225.html]
 [test_bug570341.html]
 skip-if = (toolkit == 'gonk' && debug) || (android_version == '18' && debug) #debug-only failure, android bug 1040769
 [test_bug580069.html]
 [test_bug590573.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 823022 # b2g(queryinterfaces into webnavigation, might suffer from something similar as bug 823022) b2g-debug(queryinterfaces into webnavigation, might suffer from something similar as bug 823022) b2g-desktop(queryinterfaces into webnavigation, might suffer from something similar as bug 823022)
+skip-if = buildapp == 'b2g' #bug 823022 # b2g(queryinterfaces into webnavigation, might suffer from something similar as bug 823022) b2g-debug(queryinterfaces into webnavigation, might suffer from something similar as bug 823022) b2g-desktop(queryinterfaces into webnavigation, might suffer from something similar as bug 823022)
 [test_bug598895.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #Bug 931116, b2g desktop specific, initial triage
 [test_bug634834.html]
 [test_bug637644.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #Bug 931116, b2g desktop specific, initial triage
 [test_bug640387_1.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug640387_2.html]
--- a/docshell/test/test_bug590573.html
+++ b/docshell/test/test_bug590573.html
@@ -186,33 +186,23 @@ function pageLoad()
   else if (loads == 5) {
     // Spin the event loop again so that we get the right scroll positions.
     setTimeout(pageLoad, 0);
   }
   else if (loads == 6) {
     is(popup.location.search, "?pushed");
     ok(popup.document.getElementById('div1'), 'page should have div1.');
 
-    // Bug 821821, on android 4.0.4 on panda we get 199 instead of 200
-    if (popup.scrollY >= 199 && popup.scrollY <= 200) {
-      is(1, 1, "test 8");
-    } else {
-      is(1, 0, "test 8, got " + popup.scrollY + " for popup.scrollY instead of 199|200");
-    }
+    is(popup.scrollY, 200, "test 8");
 
     popup.history.back();
     is(popup.scrollY, 150, "test 9");
     popup.history.forward();
 
-    // Bug 821821, on android 4.0.4 on panda we get 199 instead of 200
-    if (popup.scrollY >= 199 && popup.scrollY <= 200) {
-      is(1, 1, "test 10");
-    } else {
-      is(1, 0, "test 10, got " + popup.scrollY + " for popup.scrollY instead of 199|200");
-    }
+    is(popup.scrollY, 200, "test 10");
 
     // Spin one last time...
     setTimeout(pageLoad, 0);
   }
   else if (loads == 7) {
     page2PageShowCallbackEnabled = true;
     popup.history.forward();
   }
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -180,24 +180,24 @@ KeyframeEffectReadOnly::NotifyAnimationT
   // Bug 1216843: When we implement iteration composite modes, we need to
   // also detect if the current iteration has changed.
   if (mAnimation && GetComputedTiming().mProgress != mProgressOnLastCompose) {
     EffectCompositor::RestyleType restyleType =
       CanThrottle() ?
       EffectCompositor::RestyleType::Throttled :
       EffectCompositor::RestyleType::Standard;
     RequestRestyle(restyleType);
+  }
 
-    // If we're not relevant, we will have been removed from the EffectSet.
-    // As a result, when the restyle we requested above is fulfilled, our
-    // ComposeStyle will not get called and mProgressOnLastCompose will not
-    // be updated. Instead, we need to manually clear it.
-    if (!isRelevant) {
-      mProgressOnLastCompose.SetNull();
-    }
+  // If we're no longer "in effect", our ComposeStyle method will never be
+  // called and we will never have a chance to update mProgressOnLastCompose.
+  // We clear mProgressOnLastCompose here to ensure that if we later become
+  // "in effect" we will request a restyle (above).
+  if (!inEffect) {
+     mProgressOnLastCompose.SetNull();
   }
 }
 
 Nullable<TimeDuration>
 KeyframeEffectReadOnly::GetLocalTime() const
 {
   // Since the *animation* start time is currently always zero, the local
   // time is equal to the parent time.
--- a/dom/base/AnonymousContent.cpp
+++ b/dom/base/AnonymousContent.cpp
@@ -24,17 +24,17 @@ NS_IMPL_CYCLE_COLLECTION(AnonymousConten
 AnonymousContent::AnonymousContent(Element* aContentNode) :
   mContentNode(aContentNode)
 {}
 
 AnonymousContent::~AnonymousContent()
 {
 }
 
-nsCOMPtr<Element>
+Element*
 AnonymousContent::GetContentNode()
 {
   return mContentNode;
 }
 
 void
 AnonymousContent::SetContentNode(Element* aContentNode)
 {
--- a/dom/base/AnonymousContent.h
+++ b/dom/base/AnonymousContent.h
@@ -20,17 +20,17 @@ class Element;
 class AnonymousContent final
 {
 public:
   // Ref counting and cycle collection
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnonymousContent)
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AnonymousContent)
 
   explicit AnonymousContent(Element* aContentNode);
-  nsCOMPtr<Element> GetContentNode();
+  Element* GetContentNode();
   void SetContentNode(Element* aContentNode);
   bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
 
   // WebIDL methods
   void SetTextContentForElement(const nsAString& aElementId,
                                 const nsAString& aText,
                                 ErrorResult& aRv);
 
--- a/dom/base/ImportManager.h
+++ b/dom/base/ImportManager.h
@@ -154,28 +154,34 @@ public:
   {
     return mDocument;
   }
 
   // Getter for the import document that is used in the spec. Returns
   // nullptr if the import is not yet ready.
   nsIDocument* GetImport()
   {
-    return mReady ? mDocument : nullptr;
+    if (!mReady) {
+      return nullptr;
+    }
+    return mDocument;
   }
 
   // There is only one referring link that is marked as primary link per
   // imports. This is the one that has to be taken into account when
   // scrip execution order is determined. Links marked as primary link form
   // a spanning tree in the import graph. (Eliminating the cycles and
   // multiple parents.) This spanning tree is recalculated every time
   // a new import link is added to the manager.
   nsINode* GetMainReferrer()
   {
-    return mLinks.IsEmpty() ? nullptr : mLinks[mMainReferrer];
+    if (mLinks.IsEmpty()) {
+      return nullptr;
+    }
+    return mLinks[mMainReferrer];
   }
 
   // An import is not only blocked by its import children, but also
   // by its predecessors. It's enough to find the closest predecessor
   // and wait for that to run its scripts. We keep track of all the
   // ScriptRunners that are waiting for this import. NOTE: updating
   // the main referrer might change this list.
   void AddBlockedScriptLoader(nsScriptLoader* aScriptLoader);
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -47,17 +47,20 @@ public:
 
   static void Pop(ScriptSettingsStackEntry *aEntry) {
     MOZ_ASSERT(aEntry == Top());
     sScriptSettingsTLS.set(aEntry->mOlder);
   }
 
   static nsIGlobalObject* IncumbentGlobal() {
     ScriptSettingsStackEntry *entry = Top();
-    return entry ? entry->mGlobalObject : nullptr;
+    if (!entry) {
+      return nullptr;
+    }
+    return entry->mGlobalObject;
   }
 
   static ScriptSettingsStackEntry* EntryPoint() {
     ScriptSettingsStackEntry *entry = Top();
     if (!entry) {
       return nullptr;
     }
     while (entry) {
@@ -65,17 +68,20 @@ public:
         return entry;
       entry = entry->mOlder;
     }
     MOZ_CRASH("Non-empty stack should always have an entry point");
   }
 
   static nsIGlobalObject* EntryGlobal() {
     ScriptSettingsStackEntry *entry = EntryPoint();
-    return entry ? entry->mGlobalObject : nullptr;
+    if (!entry) {
+      return nullptr;
+    }
+    return entry->mGlobalObject;
   }
 
 };
 
 static unsigned long gRunToCompletionListeners = 0;
 
 void
 UseEntryScriptProfiling()
--- a/dom/base/nsAttrAndChildArray.cpp
+++ b/dom/base/nsAttrAndChildArray.cpp
@@ -376,22 +376,22 @@ nsAttrAndChildArray::GetAttr(const nsASt
 }
 
 const nsAttrValue*
 nsAttrAndChildArray::AttrAt(uint32_t aPos) const
 {
   NS_ASSERTION(aPos < AttrCount(),
                "out-of-bounds access in nsAttrAndChildArray");
 
-  uint32_t mapped = MappedAttrCount();
-  if (aPos < mapped) {
-    return mImpl->mMappedAttrs->AttrAt(aPos);
+  uint32_t nonmapped = NonMappedAttrCount();
+  if (aPos < nonmapped) {
+    return &ATTRS(mImpl)[aPos].mValue;
   }
 
-  return &ATTRS(mImpl)[aPos - mapped].mValue;
+  return mImpl->mMappedAttrs->AttrAt(aPos - nonmapped);
 }
 
 nsresult
 nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
 {
   uint32_t i, slotCount = AttrSlotCount();
   for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
     if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) {
@@ -449,81 +449,79 @@ nsAttrAndChildArray::SetAndSwapAttr(mozi
 }
 
 
 nsresult
 nsAttrAndChildArray::RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue)
 {
   NS_ASSERTION(aPos < AttrCount(), "out-of-bounds");
 
-  uint32_t mapped = MappedAttrCount();
-  if (aPos < mapped) {
-    if (mapped == 1) {
-      // We're removing the last mapped attribute.  Can't swap in this
-      // case; have to copy.
-      aValue.SetTo(*mImpl->mMappedAttrs->AttrAt(0));
-      NS_RELEASE(mImpl->mMappedAttrs);
+  uint32_t nonmapped = NonMappedAttrCount();
+  if (aPos < nonmapped) {
+    ATTRS(mImpl)[aPos].mValue.SwapValueWith(aValue);
+    ATTRS(mImpl)[aPos].~InternalAttr();
 
-      return NS_OK;
-    }
+    uint32_t slotCount = AttrSlotCount();
+    memmove(&ATTRS(mImpl)[aPos],
+            &ATTRS(mImpl)[aPos + 1],
+            (slotCount - aPos - 1) * sizeof(InternalAttr));
+    memset(&ATTRS(mImpl)[slotCount - 1], 0, sizeof(InternalAttr));
 
-    RefPtr<nsMappedAttributes> mapped =
-      GetModifiableMapped(nullptr, nullptr, false);
-
-    mapped->RemoveAttrAt(aPos, aValue);
-
-    return MakeMappedUnique(mapped);
+    return NS_OK;
   }
 
-  aPos -= mapped;
-  ATTRS(mImpl)[aPos].mValue.SwapValueWith(aValue);
-  ATTRS(mImpl)[aPos].~InternalAttr();
+  if (MappedAttrCount() == 1) {
+    // We're removing the last mapped attribute.  Can't swap in this
+    // case; have to copy.
+    aValue.SetTo(*mImpl->mMappedAttrs->AttrAt(0));
+    NS_RELEASE(mImpl->mMappedAttrs);
 
-  uint32_t slotCount = AttrSlotCount();
-  memmove(&ATTRS(mImpl)[aPos],
-          &ATTRS(mImpl)[aPos + 1],
-          (slotCount - aPos - 1) * sizeof(InternalAttr));
-  memset(&ATTRS(mImpl)[slotCount - 1], 0, sizeof(InternalAttr));
+    return NS_OK;
+  }
 
-  return NS_OK;
+  RefPtr<nsMappedAttributes> mapped =
+    GetModifiableMapped(nullptr, nullptr, false);
+
+  mapped->RemoveAttrAt(aPos - nonmapped, aValue);
+
+  return MakeMappedUnique(mapped);
 }
 
 const nsAttrName*
 nsAttrAndChildArray::AttrNameAt(uint32_t aPos) const
 {
   NS_ASSERTION(aPos < AttrCount(),
                "out-of-bounds access in nsAttrAndChildArray");
 
-  uint32_t mapped = MappedAttrCount();
-  if (aPos < mapped) {
-    return mImpl->mMappedAttrs->NameAt(aPos);
+  uint32_t nonmapped = NonMappedAttrCount();
+  if (aPos < nonmapped) {
+    return &ATTRS(mImpl)[aPos].mName;
   }
 
-  return &ATTRS(mImpl)[aPos - mapped].mName;
+  return mImpl->mMappedAttrs->NameAt(aPos - nonmapped);
 }
 
 const nsAttrName*
 nsAttrAndChildArray::GetSafeAttrNameAt(uint32_t aPos) const
 {
-  uint32_t mapped = MappedAttrCount();
-  if (aPos < mapped) {
-    return mImpl->mMappedAttrs->NameAt(aPos);
+  uint32_t nonmapped = NonMappedAttrCount();
+  if (aPos < nonmapped) {
+    void** pos = mImpl->mBuffer + aPos * ATTRSIZE;
+    if (!*pos) {
+      return nullptr;
+    }
+
+    return &reinterpret_cast<InternalAttr*>(pos)->mName;
   }
 
-  aPos -= mapped;
-  if (aPos >= AttrSlotCount()) {
+  if (aPos >= AttrCount()) {
     return nullptr;
   }
 
-  void** pos = mImpl->mBuffer + aPos * ATTRSIZE;
-  if (!*pos) {
-    return nullptr;
-  }
-
-  return &reinterpret_cast<InternalAttr*>(pos)->mName;
+  return mImpl->mMappedAttrs->NameAt(aPos - nonmapped);
 }
 
 const nsAttrName*
 nsAttrAndChildArray::GetExistingAttrNameFromQName(const nsAString& aName) const
 {
   uint32_t i, slotCount = AttrSlotCount();
   for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
     if (ATTRS(mImpl)[i].mName.QualifiedNameEquals(aName)) {
@@ -540,35 +538,34 @@ nsAttrAndChildArray::GetExistingAttrName
 
 int32_t
 nsAttrAndChildArray::IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID) const
 {
   int32_t idx;
   if (mImpl && mImpl->mMappedAttrs && aNamespaceID == kNameSpaceID_None) {
     idx = mImpl->mMappedAttrs->IndexOfAttr(aLocalName);
     if (idx >= 0) {
-      return idx;
+      return NonMappedAttrCount() + idx;
     }
   }
 
   uint32_t i;
-  uint32_t mapped = MappedAttrCount();
   uint32_t slotCount = AttrSlotCount();
   if (aNamespaceID == kNameSpaceID_None) {
     // This should be the common case so lets make an optimized loop
     for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
       if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) {
-        return i + mapped;
+        return i;
       }
     }
   }
   else {
     for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
       if (ATTRS(mImpl)[i].mName.Equals(aLocalName, aNamespaceID)) {
-        return i + mapped;
+        return i;
       }
     }
   }
 
   return -1;
 }
 
 nsresult
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -8554,18 +8554,17 @@ StartElement(Element* aContent, StringBu
   if (aContent->IsHTMLElement() || aContent->IsSVGElement() ||
       aContent->IsMathMLElement()) {
     aBuilder.Append(localName);
   } else {
     aBuilder.Append(aContent->NodeName());
   }
 
   int32_t count = aContent->GetAttrCount();
-  for (int32_t i = count; i > 0;) {
-    --i;
+  for (int32_t i = 0; i < count; i++) {
     const nsAttrName* name = aContent->GetAttrNameAt(i);
     int32_t attNs = name->NamespaceID();
     nsIAtom* attName = name->LocalName();
 
     // Filter out any attribute starting with [-|_]moz
     nsDependentAtomString attrNameStr(attName);
     if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
         StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -1343,19 +1343,19 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   otherParentItem->AddChild(ourDocshell);
 
   // Restore the correct chrome event handlers.
   ourDocshell->SetChromeEventHandler(otherChromeEventHandler);
   otherDocshell->SetChromeEventHandler(ourChromeEventHandler);
   // Restore the correct treeowners
   // (and also chrome event handlers for content frames only).
   SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourDocshell, otherOwner,
-    ourType == nsIDocShellTreeItem::typeContent ? otherChromeEventHandler : nullptr);
+    ourType == nsIDocShellTreeItem::typeContent ? otherChromeEventHandler.get() : nullptr);
   SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherDocshell, ourOwner,
-    ourType == nsIDocShellTreeItem::typeContent ? ourChromeEventHandler : nullptr);
+    ourType == nsIDocShellTreeItem::typeContent ? ourChromeEventHandler.get() : nullptr);
 
   // Switch the owner content before we start calling AddTreeItemToTreeOwner.
   // Note that we rely on this to deal with setting mObservingOwnerContent to
   // false and calling RemoveMutationObserver as needed.
   SetOwnerContent(otherContent);
   aOther->SetOwnerContent(ourContent);
 
   AddTreeItemToTreeOwner(ourDocshell, otherOwner, otherParentType, nullptr);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2080,17 +2080,20 @@ nsGlobalWindow::EnsureScriptEnvironment(
   outer->mContext = context;
   return NS_OK;
 }
 
 nsIScriptContext *
 nsGlobalWindow::GetScriptContext()
 {
   nsGlobalWindow* outer = GetOuterWindowInternal();
-  return outer ? outer->mContext : nullptr;
+  if (!outer) {
+    return nullptr;
+  }
+  return outer->mContext;
 }
 
 JSObject *
 nsGlobalWindow::GetGlobalJSObject()
 {
   return FastGetGlobalJSObject();
 }
 
@@ -3805,16 +3808,19 @@ nsPIDOMWindowOuter::SetServiceWorkersTes
 }
 
 bool
 nsPIDOMWindowOuter::GetServiceWorkersTestingEnabled()
 {
   // Automatically get this setting from the top level window so that nested
   // iframes get the correct devtools setting.
   nsCOMPtr<nsPIDOMWindowOuter> topWindow = GetScriptableTop();
+  if (!topWindow) {
+    return false;
+  }
   return topWindow->mServiceWorkersTestingEnabled;
 }
 
 bool
 nsPIDOMWindowInner::GetAudioCaptured() const
 {
   MOZ_ASSERT(IsInnerWindow());
   return mAudioCaptured;
@@ -7071,17 +7077,17 @@ nsGlobalWindow::PrintOuter(ErrorResult& 
     aError.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
   nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint;
   if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint),
                                 getter_AddRefs(webBrowserPrint)))) {
     nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ?
-                               GetCurrentInnerWindowInternal()->mDoc :
+                               GetCurrentInnerWindowInternal()->mDoc.get() :
                                nullptr);
 
     nsCOMPtr<nsIPrintSettingsService> printSettingsService =
       do_GetService("@mozilla.org/gfx/printsettings-service;1");
 
     nsCOMPtr<nsIPrintSettings> printSettings;
     if (printSettingsService) {
       bool printSettingsAreGlobal =
--- a/dom/base/nsHTMLContentSerializer.cpp
+++ b/dom/base/nsHTMLContentSerializer.cpp
@@ -77,18 +77,17 @@ nsHTMLContentSerializer::SerializeHTMLAt
   int32_t count = aContent->GetAttrCount();
   if (!count)
     return true;
 
   nsresult rv;
   nsAutoString valueStr;
   NS_NAMED_LITERAL_STRING(_mozStr, "_moz");
 
-  for (int32_t index = count; index > 0;) {
-    --index;
+  for (int32_t index = 0; index < count; index++) {
     const nsAttrName* name = aContent->GetAttrNameAt(index);
     int32_t namespaceID = name->NamespaceID();
     nsIAtom* attrName = name->LocalName();
 
     // Filter out any attribute starting with [-|_]moz
     nsDependentAtomString attrNameStr(attrName);
     if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
         StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
--- a/dom/base/nsXMLHttpRequest.cpp
+++ b/dom/base/nsXMLHttpRequest.cpp
@@ -543,17 +543,20 @@ nsXMLHttpRequest::GetResponseXML(ErrorRe
       mResponseType != XML_HTTP_RESPONSE_TYPE_DOCUMENT) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
   if (mWarnAboutSyncHtml) {
     mWarnAboutSyncHtml = false;
     LogMessage("HTMLSyncXHRWarning", GetOwner());
   }
-  return (XML_HTTP_REQUEST_DONE & mState) ? mResponseXML : nullptr;
+  if (!(XML_HTTP_REQUEST_DONE & mState)) {
+    return nullptr;
+  }
+  return mResponseXML;
 }
 
 /*
  * This piece copied from XMLDocument, we try to get the charset
  * from HTTP headers.
  */
 nsresult
 nsXMLHttpRequest::DetectCharset()
--- a/dom/base/test/test_bug422403-2.xhtml
+++ b/dom/base/test/test_bug422403-2.xhtml
@@ -219,42 +219,42 @@ function testHtmlSerializer_1 () {
   out = encoder.encodeToString();
   expected = '<select xmlns="http://www.w3.org/1999/xhtml" id="shortattr5" multiple="multiple"><option selected="selected">aaa</option></select>';
   is(out, expected, "test short attr #5");
 
   node = document.getElementById('shortattr6');
   encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
   encoder.setNode(node);
   out = encoder.encodeToString();
-  expected = '<hr xmlns="http://www.w3.org/1999/xhtml" noshade="noshade" id="shortattr6" />';
+  expected = '<hr xmlns="http://www.w3.org/1999/xhtml" id="shortattr6" noshade="noshade" />';
   is(out, expected, "test short attr #6");
 
   node = document.getElementById('shortattr7');
   encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
   encoder.setNode(node);
   out = encoder.encodeToString();
   expected = '<div xmlns="http://www.w3.org/1999/xhtml" id="shortattr7"><foo:bar xmlns:foo="http://mozilla.org/ns/any" checked="" value="" disabled="" ismap="" readonly=""/></div>';
   is(out, expected, "test short attr #7");
 
   // test on _moz and -moz attr
   node = document.getElementById('mozattr');
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
   encoder.setNode(node);
   out = encoder.encodeToString();
-  expected = '<div __moz_b="b" id="mozattr"> lorem ipsum</div>';
+  expected = '<div id="mozattr" __moz_b="b"> lorem ipsum</div>';
   is(out, expected, "test -moz/_moz attr");
 
   node.setAttribute('_moz_c','barc');
   node.setAttribute('_-moz_d','bard');
   node.setAttribute('__moz_e','bare');
 
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
   encoder.setNode(node);
   out = encoder.encodeToString();
-  expected = '<div __moz_e="bare" _-moz_d="bard" __moz_b="b" id="mozattr"> lorem ipsum</div>';
+  expected = '<div id="mozattr" __moz_b="b" _-moz_d="bard" __moz_e="bare"> lorem ipsum</div>';
   is(out, expected, "test -moz/_moz attr #2");
 
   SimpleTest.finish();
 }
 
 
 SimpleTest.waitForExplicitFinish();
 
@@ -279,17 +279,17 @@ addLoadEvent(testHtmlSerializer_1);
 
 <!-- test for some short attr -->
 <div id="shortattr" xmlns:foo="http://mozilla.org/ns/any">
    <input id="shortattr1" checked="" value="" disabled="" ismap="" readonly="" foo:checked="" foo:disabled=""/>
    <ol id="shortattr2" compact=""><li></li></ol>
    <object id="shortattr3" declare="" />
    <script id="shortattr4" defer="" />
    <select id="shortattr5" multiple=""><option selected="">aaa</option></select>
-   <hr noshade="" id="shortattr6"/>
+   <hr id="shortattr6" noshade=""/>
    <div id="shortattr7"><foo:bar checked="" value="" disabled="" ismap="" readonly="" /></div>
    <div id="mozattr" _moz_a="a" __moz_b="b"> lorem ipsum</div>
 </div>
 
 </div>
 </body>
 </html>
 
--- a/dom/base/test/test_bug424359-2.html
+++ b/dom/base/test/test_bug424359-2.html
@@ -169,17 +169,17 @@ function testHtmlSerializer_1 () {
 
   // selection start at the third child of the ol, and end after the element ol + ol start at the value 5
   range.setStart(node, 3);
   range.setEnd(node.parentNode, 2);
   node.setAttribute("start","5");
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
   encoder.setSelection(select);
   out = encoder.encodeToString();
-  expected = '<ol start="5" id="aList"><li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  expected = '<ol id="aList" start="5"><li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
   is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol + ol start at the value 5");
 
 
   // selection contains only some child of the ol
   node.removeAttribute("start");
   range.setStart(node, 3);
   range.setEnd(node, 5);
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
@@ -267,17 +267,17 @@ function testHtmlSerializer_1 () {
 
   node.setAttribute('_moz_c','barc');
   node.setAttribute('_-moz_d','bard');
   node.setAttribute('__moz_e','bare');
 
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
   encoder.setNode(node);
   out = encoder.encodeToString();
-  expected = '<div __moz_e="bare" _-moz_d="bard" id="mozattr" __moz_b="b"> lorem ipsum</div>';
+  expected = '<div id="mozattr" __moz_b="b" _-moz_d="bard" __moz_e="bare"> lorem ipsum</div>';
   is(out, expected, "test -moz/_moz attr #2");
 
   SimpleTest.finish();
 }
 
 
 SimpleTest.waitForExplicitFinish();
 
@@ -312,9 +312,9 @@ addLoadEvent(testHtmlSerializer_1);
    <div id="shortattr7"><foo checked="" value="" disabled="" ismap="" readonly=""></div>
    <div id="mozattr" _moz_a="a" __moz_b="b"> lorem ipsum</div>
 </div>
 
 
 
 </div>
 </body>
-</html>
\ No newline at end of file
+</html>
--- a/dom/base/test/test_bug744830.html
+++ b/dom/base/test/test_bug744830.html
@@ -49,29 +49,29 @@ https://bugzilla.mozilla.org/show_bug.cg
   t.appendChild(document.createElementNS("http://www.example.org", "example"));
   t.firstChild.textContent = "<foo>";
   is(t.innerHTML, "<example>&lt;foo&gt;</example>");
 
   t.firstChild.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang", "us-en");
   is(t.innerHTML, '<example xml:lang="us-en">&lt;foo&gt;</example>');
 
   t.firstChild.setAttributeNS("http://www.w3.org/1999/xlink", "href", "foo");
-  is(t.innerHTML, '<example xlink:href="foo" xml:lang="us-en">&lt;foo&gt;</example>');
+  is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo">&lt;foo&gt;</example>');
 
   t.firstChild.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://foo");
-  is(t.innerHTML, '<example xmlns="http://foo" xlink:href="foo" xml:lang="us-en">&lt;foo&gt;</example>');
+  is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo" xmlns="http://foo">&lt;foo&gt;</example>');
 
   t.firstChild.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:bar", "http://bar");
-  is(t.innerHTML, '<example xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en">&lt;foo&gt;</example>');
+  is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo" xmlns="http://foo" xmlns:bar="http://bar">&lt;foo&gt;</example>');
   
   t.firstChild.setAttributeNS("http://www.helloworldns.org", "hello:world", "!");
-  is(t.innerHTML, '<example hello:world="!" xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en">&lt;foo&gt;</example>');
+  is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo" xmlns="http://foo" xmlns:bar="http://bar" hello:world="!">&lt;foo&gt;</example>');
 
   t.firstChild.setAttribute("foo", '-"&\xA0-');
-  is(t.innerHTML, '<example foo="-&quot;&amp;&nbsp;-" hello:world="!" xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en">&lt;foo&gt;</example>');
+  is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo" xmlns="http://foo" xmlns:bar="http://bar" hello:world="!" foo="-&quot;&amp;&nbsp;-">&lt;foo&gt;</example>');
 
   t.innerHTML = null;
   t.appendChild(document.createElement("div"));
   t.firstChild.appendChild(document.implementation
                                    .createDocument(null, null, null)
                                    .createCDATASection("foo"));
   is(t.innerHTML, '<div>foo</div>');
 
--- a/dom/base/test/test_htmlcopyencoder.html
+++ b/dom/base/test/test_htmlcopyencoder.html
@@ -113,17 +113,17 @@ function testHtmlCopyEncoder () {
 
   // selection start at the third child of the ol, and end after the element ol + ol start at the value 5
   range.setStart(node, 3);
   range.setEnd(node.parentNode, 2);
   node.setAttribute("start","5");
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
   encoder.setSelection(select);
   out = encoder.encodeToString();
-  expected = '<ol start=\"5\" id=\"aList\"><li value=\"6\">sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  expected = '<ol id=\"aList\" start=\"5\"><li value=\"6\">sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
   is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol + ol start at the value 5");
 
   // selection contains only some child of the ol
   node.removeAttribute("start");
   range.setStart(node, 3);
   range.setEnd(node, 5);
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
   encoder.setSelection(select);
--- a/dom/base/test/test_htmlcopyencoder.xhtml
+++ b/dom/base/test/test_htmlcopyencoder.xhtml
@@ -33,21 +33,17 @@ function testHtmlCopyEncoder () {
   encoder.setContainerNode(node);
   out = encoder.encodeToString();
   expected = 'This is a <em>draggable</em> <br>bit of text.';
   is(out, expected, "test container node ");
 
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
   encoder.setNode(node);
   out = encoder.encodeToString();
-  // the attributes are in the reverse order because the XHTML parser parse in the
-  // right order but the html serializer serializes in the reverse order
-  // (because the html parser stores the attribute in the reverse order,
-  // see bug 213347 for reason).
-  expected = "<div ondragstart=\"doDragStartSelection(event)\" id=\"draggable\">This is a <em>draggable</em> <br>bit of text.</div>";
+  expected = "<div id=\"draggable\" ondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em> <br>bit of text.</div>";
   is(out, expected, "test node");
 
   var select = window.getSelection();
   select.selectAllChildren(node);
   
   encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
   encoder.setSelection(select);
   out = encoder.encodeToString();
--- a/dom/canvas/OffscreenCanvas.cpp
+++ b/dom/canvas/OffscreenCanvas.cpp
@@ -217,17 +217,18 @@ OffscreenCanvas::ToCloneData()
   return new OffscreenCanvasCloneData(mCanvasRenderer, mWidth, mHeight,
                                       mCompositorBackendType, mNeutered, mIsWriteOnly);
 }
 
 already_AddRefed<ImageBitmap>
 OffscreenCanvas::TransferToImageBitmap()
 {
   ErrorResult rv;
-  RefPtr<ImageBitmap> result = ImageBitmap::CreateFromOffscreenCanvas(GetGlobalObject(), *this, rv);
+  nsCOMPtr<nsIGlobalObject> globalObject = GetGlobalObject();
+  RefPtr<ImageBitmap> result = ImageBitmap::CreateFromOffscreenCanvas(globalObject, *this, rv);
 
   // Clear the content.
   if ((mCurrentContextType == CanvasContextType::WebGL1 ||
        mCurrentContextType == CanvasContextType::WebGL2))
   {
     WebGLContext* webGL = static_cast<WebGLContext*>(mCurrentContext.get());
     webGL->ClearScreen();
   }
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1902,17 +1902,17 @@ class HTMLMediaElement::CaptureStreamTra
   public DecoderPrincipalChangeObserver
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CaptureStreamTrackSource,
                                            MediaStreamTrackSource)
 
   explicit CaptureStreamTrackSource(HTMLMediaElement* aElement)
-    : MediaStreamTrackSource(nsCOMPtr<nsIPrincipal>(aElement->GetCurrentPrincipal()),
+    : MediaStreamTrackSource(nsCOMPtr<nsIPrincipal>(aElement->GetCurrentPrincipal()).get(),
                              true,
                              nsString())
     , mElement(aElement)
   {
     MOZ_ASSERT(mElement);
     mElement->AddDecoderPrincipalChangeObserver(this);
   }
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -1876,17 +1876,18 @@ MediaDecoder::NextFrameBufferedStatus()
     : MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
 }
 
 void
 MediaDecoder::DumpDebugInfo()
 {
   DUMP_LOG("metadata: channels=%u rate=%u hasAudio=%d hasVideo=%d, "
            "state: mPlayState=%s mIsDormant=%d, mShuttingDown=%d",
-           mInfo->mAudio.mChannels, mInfo->mAudio.mRate, mInfo->HasAudio(), mInfo->HasVideo(),
+           mInfo ? mInfo->mAudio.mChannels : 0, mInfo ? mInfo->mAudio.mRate : 0,
+           mInfo ? mInfo->HasAudio() : 0, mInfo ? mInfo->HasVideo() : 0,
            PlayStateStr(), mIsDormant, mShuttingDown);
 
   nsString str;
   GetMozDebugReaderData(str);
   DUMP_LOG("reader data:\n%s", NS_ConvertUTF16toUTF8(str).get());
 
   if (!mShuttingDown && GetStateMachine()) {
     GetStateMachine()->DumpDebugInfo();
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -1167,17 +1167,16 @@ RTCPeerConnection.prototype = {
 
   get localDescription() {
     this._checkClosed();
     let sdp = this._impl.localDescription;
     if (sdp.length == 0) {
       return null;
     }
 
-    sdp = this._localIdp.addIdentityAttribute(sdp);
     return new this._win.RTCSessionDescription({ type: this._localType,
                                                     sdp: sdp });
   },
 
   get remoteDescription() {
     this._checkClosed();
     let sdp = this._impl.remoteDescription;
     if (sdp.length == 0) {
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -71,17 +71,17 @@ public:
 
     base::ProcessId otherProcess;
     nsCString displayName;
     uint32_t pluginId;
     nsresult rv;
     bool ok = aGMPServiceChild->SendLoadGMP(mNodeId, mAPI, mTags,
                                             alreadyBridgedTo, &otherProcess,
                                             &displayName, &pluginId, &rv);
-    if (!ok && rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) {
+    if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) {
       mCallback->Done(nullptr);
       return;
     }
 
     RefPtr<GMPContentParent> parent;
     aGMPServiceChild->GetBridgedGMPContentParent(otherProcess,
                                                  getter_AddRefs(parent));
     if (!alreadyBridgedTo.Contains(otherProcess)) {
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -998,19 +998,16 @@ TrackBuffersManager::OnDemuxerInitDone(n
     // then the Track IDs match the ones in the first initialization segment.
     // TODO
     // 2. Add the appropriate track descriptions from this initialization
     // segment to each of the track buffers.
     // TODO
     // 3. Set the need random access point flag on all track buffers to true.
     mVideoTracks.mNeedRandomAccessPoint = true;
     mAudioTracks.mNeedRandomAccessPoint = true;
-
-    mVideoTracks.mLongestFrameDuration = mVideoTracks.mLastFrameDuration;
-    mAudioTracks.mLongestFrameDuration = mAudioTracks.mLastFrameDuration;
   }
 
   // 4. Let active track flag equal false.
   bool activeTrack = false;
 
   // Increase our stream id.
   uint32_t streamID = sStreamSourceID++;
 
@@ -1386,28 +1383,25 @@ TrackBuffersManager::ProcessFrames(Track
   // Some videos do not exactly start at 0, but instead a small negative value.
   // To avoid evicting the starting frame of those videos, we allow a leeway
   // of +- mLongestFrameDuration on the append window start.
   // We only apply the leeway with the default append window start of 0
   // otherwise do as per spec.
   TimeInterval targetWindow = mAppendWindow.mStart != TimeUnit::FromSeconds(0)
     ? mAppendWindow
     : TimeInterval(mAppendWindow.mStart, mAppendWindow.mEnd,
-                   trackBuffer.mLongestFrameDuration.refOr(TimeUnit::FromMicroseconds(aSamples[0]->mDuration)));
+                   trackBuffer.mLastFrameDuration.isSome()
+                     ? trackBuffer.mLongestFrameDuration
+                     : TimeUnit::FromMicroseconds(aSamples[0]->mDuration));
 
   TimeIntervals samplesRange;
   uint32_t sizeNewSamples = 0;
   TrackBuffer samples; // array that will contain the frames to be added
                        // to our track buffer.
 
-  // We assume that no frames are contiguous within a media segment and as such
-  // don't need to check for discontinuity except for the first frame and should
-  // a frame be ignored due to the target window.
-  bool needDiscontinuityCheck = true;
-
   if (aSamples.Length()) {
     aTrackData.mLastParsedEndTime = TimeUnit();
   }
 
   for (auto& sample : aSamples) {
     SAMPLE_DEBUG("Processing %s frame(pts:%lld end:%lld, dts:%lld, duration:%lld, "
                "kf:%d)",
                aTrackData.mInfo->mMimeType.get(),
@@ -1443,34 +1437,39 @@ TrackBuffersManager::ProcessFrames(Track
     // Otherwise:
     //   Let presentation timestamp be a double precision floating point representation of the coded frame's presentation timestamp in seconds.
     //   Let decode timestamp be a double precision floating point representation of the coded frame's decode timestamp in seconds.
 
     // 2. Let frame duration be a double precision floating point representation of the coded frame's duration in seconds.
     // Step 3 is performed earlier or when a discontinuity has been detected.
     // 4. If timestampOffset is not 0, then run the following steps:
 
+    TimeUnit sampleTime = TimeUnit::FromMicroseconds(sample->mTime);
+    TimeUnit sampleTimecode = TimeUnit::FromMicroseconds(sample->mTimecode);
+    TimeUnit sampleDuration = TimeUnit::FromMicroseconds(sample->mDuration);
+    TimeUnit timestampOffset = mSourceBufferAttributes->GetTimestampOffset();
+
     TimeInterval sampleInterval =
       mSourceBufferAttributes->mGenerateTimestamps
-        ? TimeInterval(mSourceBufferAttributes->GetTimestampOffset(),
-                       mSourceBufferAttributes->GetTimestampOffset() + TimeUnit::FromMicroseconds(sample->mDuration))
-        : TimeInterval(TimeUnit::FromMicroseconds(sample->mTime) + mSourceBufferAttributes->GetTimestampOffset(),
-                       TimeUnit::FromMicroseconds(sample->GetEndTime()) + mSourceBufferAttributes->GetTimestampOffset());
+        ? TimeInterval(timestampOffset, timestampOffset + sampleDuration)
+        : TimeInterval(timestampOffset + sampleTime,
+                       timestampOffset + sampleTime + sampleDuration);
     TimeUnit decodeTimestamp =
       mSourceBufferAttributes->mGenerateTimestamps
-        ? mSourceBufferAttributes->GetTimestampOffset()
-        : TimeUnit::FromMicroseconds(sample->mTimecode) + mSourceBufferAttributes->GetTimestampOffset();
+        ? timestampOffset
+        : timestampOffset + sampleTimecode;
 
     // 6. If last decode timestamp for track buffer is set and decode timestamp is less than last decode timestamp:
     // OR
     // If last decode timestamp for track buffer is set and the difference between decode timestamp and last decode timestamp is greater than 2 times last frame duration:
 
-    if (needDiscontinuityCheck && trackBuffer.mLastDecodeTimestamp.isSome() &&
+    if (trackBuffer.mLastDecodeTimestamp.isSome() &&
         (decodeTimestamp < trackBuffer.mLastDecodeTimestamp.ref() ||
-         decodeTimestamp - trackBuffer.mLastDecodeTimestamp.ref() > 2*trackBuffer.mLongestFrameDuration.ref())) {
+         (decodeTimestamp - trackBuffer.mLastDecodeTimestamp.ref()
+          > 2 * trackBuffer.mLongestFrameDuration))) {
       MSE_DEBUG("Discontinuity detected.");
       SourceBufferAppendMode appendMode = mSourceBufferAttributes->GetAppendMode();
 
       // 1a. If mode equals "segments":
       if (appendMode == SourceBufferAppendMode::Segments) {
         // Set group end timestamp to presentation timestamp.
         mSourceBufferAttributes->SetGroupEndTimestamp(sampleInterval.mStart);
       }
@@ -1487,38 +1486,37 @@ TrackBuffersManager::ProcessFrames(Track
         // 5. Set the need random access point flag on all track buffers to true.
         track->ResetAppendState();
       }
       // 6. Jump to the Loop Top step above to restart processing of the current coded frame.
       // Rather that restarting the process for the frame, we run the first
       // steps again instead.
       // 3. If mode equals "sequence" and group start timestamp is set, then run the following steps:
       TimeUnit presentationTimestamp = mSourceBufferAttributes->mGenerateTimestamps
-        ? TimeUnit() : TimeUnit::FromMicroseconds(sample->mTime);
+        ? TimeUnit() : sampleTime;
       CheckSequenceDiscontinuity(presentationTimestamp);
 
       if (!sample->mKeyframe) {
         continue;
       }
       if (appendMode == SourceBufferAppendMode::Sequence) {
         // mSourceBufferAttributes->GetTimestampOffset() was modified during CheckSequenceDiscontinuity.
         // We need to update our variables.
+        timestampOffset = mSourceBufferAttributes->GetTimestampOffset();
         sampleInterval =
           mSourceBufferAttributes->mGenerateTimestamps
-            ? TimeInterval(mSourceBufferAttributes->GetTimestampOffset(),
-                           mSourceBufferAttributes->GetTimestampOffset() + TimeUnit::FromMicroseconds(sample->mDuration))
-            : TimeInterval(TimeUnit::FromMicroseconds(sample->mTime) + mSourceBufferAttributes->GetTimestampOffset(),
-                           TimeUnit::FromMicroseconds(sample->GetEndTime()) + mSourceBufferAttributes->GetTimestampOffset());
+            ? TimeInterval(timestampOffset, timestampOffset + sampleDuration)
+            : TimeInterval(timestampOffset + sampleTime,
+                           timestampOffset + sampleTime + sampleDuration);
         decodeTimestamp =
           mSourceBufferAttributes->mGenerateTimestamps
-            ? mSourceBufferAttributes->GetTimestampOffset()
-            : TimeUnit::FromMicroseconds(sample->mTimecode) + mSourceBufferAttributes->GetTimestampOffset();
+            ? timestampOffset
+            : timestampOffset + sampleTimecode;
       }
       trackBuffer.mNeedRandomAccessPoint = false;
-      needDiscontinuityCheck = false;
     }
 
     // 7. Let frame end timestamp equal the sum of presentation timestamp and frame duration.
     // This is sampleInterval.mEnd
 
     // 8. If presentation timestamp is less than appendWindowStart, then set the need random access point flag to true, drop the coded frame, and jump to the top of the loop to start processing the next coded frame.
     // 9. If frame end timestamp is greater than appendWindowEnd, then set the need random access point flag to true, drop the coded frame, and jump to the top of the loop to start processing the next coded frame.
     if (!targetWindow.ContainsWithStrictEnd(sampleInterval)) {
@@ -1527,41 +1525,39 @@ TrackBuffersManager::ProcessFrames(Track
         // Insert the samples processed so far.
         InsertFrames(samples, samplesRange, trackBuffer);
         samples.Clear();
         samplesRange = TimeIntervals();
         trackBuffer.mSizeBuffer += sizeNewSamples;
         sizeNewSamples = 0;
       }
       trackBuffer.mNeedRandomAccessPoint = true;
-      needDiscontinuityCheck = true;
       continue;
     }
 
     samplesRange += sampleInterval;
     sizeNewSamples += sample->ComputedSizeOfIncludingThis();
     sample->mTime = sampleInterval.mStart.ToMicroseconds();
     sample->mTimecode = decodeTimestamp.ToMicroseconds();
     sample->mTrackInfo = trackBuffer.mLastInfo;
     samples.AppendElement(sample);
 
     // Steps 11,12,13,14, 15 and 16 will be done in one block in InsertFrames.
 
+    trackBuffer.mLongestFrameDuration =
+      trackBuffer.mLastFrameDuration.isSome()
+      ? sample->mKeyframe
+        ? sampleDuration
+        : std::max(sampleDuration, trackBuffer.mLongestFrameDuration)
+      : sampleDuration;
+
     // 17. Set last decode timestamp for track buffer to decode timestamp.
-    trackBuffer.mLastDecodeTimestamp =
-      Some(TimeUnit::FromMicroseconds(sample->mTimecode));
+    trackBuffer.mLastDecodeTimestamp = Some(decodeTimestamp);
     // 18. Set last frame duration for track buffer to frame duration.
-    trackBuffer.mLastFrameDuration =
-      Some(TimeUnit::FromMicroseconds(sample->mDuration));
-
-    trackBuffer.mLongestFrameDuration =
-      Some(trackBuffer.mLongestFrameDuration.isNothing()
-           ? trackBuffer.mLastFrameDuration.ref()
-           : std::max(trackBuffer.mLastFrameDuration.ref(),
-                      trackBuffer.mLongestFrameDuration.ref()));
+    trackBuffer.mLastFrameDuration = Some(sampleDuration);
 
     // 19. If highest end timestamp for track buffer is unset or frame end timestamp is greater than highest end timestamp, then set highest end timestamp for track buffer to frame end timestamp.
     if (trackBuffer.mHighestEndTimestamp.isNothing() ||
         sampleInterval.mEnd > trackBuffer.mHighestEndTimestamp.ref()) {
       trackBuffer.mHighestEndTimestamp = Some(sampleInterval.mEnd);
     }
     // 20. If frame end timestamp is greater than group end timestamp, then set group end timestamp equal to frame end timestamp.
     if (sampleInterval.mEnd > mSourceBufferAttributes->GetGroupEndTimestamp()) {
@@ -1686,17 +1682,17 @@ TrackBuffersManager::InsertFrames(TrackB
   trackBuffer.mNextInsertionIndex.ref() += aSamples.Length();
 
   // Update our buffered range with new sample interval.
   trackBuffer.mBufferedRanges += aIntervals;
   // We allow a fuzz factor in our interval of half a frame length,
   // as fuzz is +/- value, giving an effective leeway of a full frame
   // length.
   TimeIntervals range(aIntervals);
-  range.SetFuzz(trackBuffer.mLongestFrameDuration.ref() / 2);
+  range.SetFuzz(trackBuffer.mLongestFrameDuration / 2);
   trackBuffer.mSanitizedBufferedRanges += range;
 }
 
 void
 TrackBuffersManager::RemoveFrames(const TimeIntervals& aIntervals,
                                   TrackData& aTrackData,
                                   uint32_t aStartIndex)
 {
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -263,18 +263,20 @@ private:
     // been appended yet.
     Maybe<media::TimeUnit> mLastFrameDuration;
     // Highest end timestamp variable that stores the highest coded frame end
     // timestamp across all coded frames in the current coded frame group that
     // were appended to this track buffer.
     // The variable is initially unset to indicate that no coded frames have
     // been appended yet.
     Maybe<media::TimeUnit> mHighestEndTimestamp;
-    // Longest frame duration seen in a coded frame group.
-    Maybe<media::TimeUnit> mLongestFrameDuration;
+    // Longest frame duration seen since last random access point.
+    // Only ever accessed when mLastDecodeTimestamp and mLastFrameDuration are
+    // set.
+    media::TimeUnit mLongestFrameDuration;
     // Need random access point flag variable that keeps track of whether the
     // track buffer is waiting for a random access point coded frame.
     // The variable is initially set to true to indicate that random access
     // point coded frame is needed before anything can be added to the track
     // buffer.
     bool mNeedRandomAccessPoint;
     RefPtr<MediaTrackDemuxer> mDemuxer;
     MozPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
@@ -313,17 +315,16 @@ private:
 
     void ResetAppendState()
     {
       mLastDecodeTimestamp.reset();
       mLastFrameDuration.reset();
       mHighestEndTimestamp.reset();
       mNeedRandomAccessPoint = true;
 
-      mLongestFrameDuration.reset();
       mNextInsertionIndex.reset();
     }
 
     void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes);
   };
 
   void CheckSequenceDiscontinuity(const media::TimeUnit& aPresentationTime);
   void ProcessFrames(TrackBuffer& aSamples, TrackData& aTrackData);
--- a/dom/media/test/test_gmp_playback.html
+++ b/dom/media/test/test_gmp_playback.html
@@ -1,40 +1,40 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test playback of media files that should play OK</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  <script type="text/javascript" src="manifest.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-function startTest() {
-  var v = document.createElement("video");
-  ok(v.canPlayType('video/mp4; codecs="avc1.64000d,mp4a.40.2"') != "",
-     "Should be able to play MP4/H.264/AAC via <video> using GMP");
-  v.src = "short.mp4";
-  v.addEventListener("ended", function(event) {
-    ok(true, "Reached end");
-    SimpleTest.finish();
-  });
-  document.body.appendChild(v);
-  v.play();
-}
-
-var testPrefs = [
-  ['media.gmp.decoder.aac', 1],  // gmp-clearkey
-  ['media.gmp.decoder.h264', 1], // gmp-clearkey
-  ['media.gmp.decoder.enabled', true]
-];
-
-SpecialPowers.pushPrefEnv({'set': testPrefs}, startTest);
-
-</script>
-</pre>
-</body>
-</html>
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test playback of media files that should play OK</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function startTest() {
+  var v = document.createElement("video");
+  ok(v.canPlayType('video/mp4; codecs="avc1.64000d,mp4a.40.2"') != "",
+     "Should be able to play MP4/H.264/AAC via <video> using GMP");
+  v.src = "short.mp4";
+  v.addEventListener("ended", function(event) {
+    ok(true, "Reached end");
+    SimpleTest.finish();
+  });
+  document.body.appendChild(v);
+  v.play();
+}
+
+var testPrefs = [
+  ['media.gmp.decoder.aac', 1],  // gmp-clearkey
+  ['media.gmp.decoder.h264', 1], // gmp-clearkey
+  ['media.gmp.decoder.enabled', true]
+];
+
+SpecialPowers.pushPrefEnv({'set': testPrefs}, startTest);
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/tests/mochitest/head.js
+++ b/dom/media/tests/mochitest/head.js
@@ -332,19 +332,22 @@ function run_test(is_initiator,timeout) 
   s.src = "/test.js";
   s.onload = () => setTestOptions(options);
   document.head.appendChild(s);
 }
 
 function runTestWhenReady(testFunc) {
   setupEnvironment();
   return testConfigured.then(options => testFunc(options))
-    .catch(e => ok(false, 'Error executing test: ' + e +
+    .catch(e => {
+      ok(false, 'Error executing test: ' + e +
         ((typeof e.stack === 'string') ?
-        (' ' + e.stack.split('\n').join(' ... ')) : '')));
+        (' ' + e.stack.split('\n').join(' ... ')) : ''));
+      SimpleTest.finish();
+    });
 }
 
 
 /**
  * Checks that the media stream tracks have the expected amount of tracks
  * with the correct kind and id based on the type and constraints given.
  *
  * @param {Object} constraints specifies whether the stream should have
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -79,16 +79,22 @@ skip-if = (toolkit == 'gonk' || buildapp
 [test_getUserMedia_stopVideoStream.html]
 [test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
 [test_getUserMedia_peerIdentity.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 1021776, too --ing slow on b2g)
 [test_peerConnection_addIceCandidate.html]
 [test_peerConnection_addTrack.html]
 [test_peerConnection_basicAudio.html]
 skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
+[test_peerConnection_basicAudioNATSrflx.html]
+skip-if = toolkit == 'gonk' || toolkit == 'android' # B2G emulator is too slow to handle a two-way audio call reliably, websockets don't work on android (bug 1266217)
+[test_peerConnection_basicAudioNATRelay.html]
+skip-if = toolkit == 'gonk' || toolkit == 'android' # B2G emulator is too slow to handle a two-way audio call reliably, websockets don't work on android (bug 1266217)
+[test_peerConnection_basicAudioNATRelayTCP.html]
+skip-if = toolkit == 'gonk' || toolkit == 'android' # B2G emulator is too slow to handle a two-way audio call reliably, websockets don't work on android (bug 1266217)
 [test_peerConnection_basicAudioRequireEOC.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
 [test_peerConnection_basicAudioPcmaPcmuOnly.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
 [test_peerConnection_basicAudioDynamicPtMissingRtpmap.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
 [test_peerConnection_basicAudioVideo.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug) # b2g(Bug 960442, video support for WebRTC is disabled on b2g), android(Bug 1189784, timeouts on 4.3 emulator)
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -59,17 +59,27 @@ function PeerConnectionTest(options) {
   options.is_local = "is_local" in options ? options.is_local : true;
   options.is_remote = "is_remote" in options ? options.is_remote : true;
 
   options.h264 = "h264" in options ? options.h264 : false;
   options.bundle = "bundle" in options ? options.bundle : true;
   options.rtcpmux = "rtcpmux" in options ? options.rtcpmux : true;
   options.opus = "opus" in options ? options.opus : true;
 
-  if (typeof turnServers !== "undefined") {
+  if (iceServersArray.length) {
+    if (!options.turn_disabled_local) {
+      options.config_local = options.config_local || {}
+      options.config_local.iceServers = iceServersArray;
+    }
+    if (!options.turn_disabled_remote) {
+      options.config_remote = options.config_remote || {}
+      options.config_remote.iceServers = iceServersArray;
+    }
+  }
+  else if (typeof turnServers !== "undefined") {
     if ((!options.turn_disabled_local) && (turnServers.local)) {
       if (!options.hasOwnProperty("config_local")) {
         options.config_local = {};
       }
       if (!options.config_local.hasOwnProperty("iceServers")) {
         options.config_local.iceServers = turnServers.local.iceServers;
       }
     }
@@ -1674,17 +1684,17 @@ PeerConnectionWrapper.prototype = {
 
   /**
    * Compares the Ice server configured for this PeerConnectionWrapper
    * with the ICE candidates received in the RTCP stats.
    *
    * @param {object} stats
    *        The stats to be verified for relayed vs. direct connection.
    */
-  checkStatsIceConnectionType : function(stats) {
+  checkStatsIceConnectionType : function(stats, expectedLocalCandidateType) {
     let lId;
     let rId;
     for (let stat of stats.values()) {
       if (stat.type == "candidatepair" && stat.selected) {
         lId = stat.localCandidateId;
         rId = stat.remoteCandidateId;
         break;
       }
@@ -1693,31 +1703,35 @@ PeerConnectionWrapper.prototype = {
     isnot(rId, undefined, "Got remote candidate ID " + rId + " for selected pair");
     let lCand = stats.get(lId);
     let rCand = stats.get(rId);
     if (!lCand || !rCand) {
       ok(false,
          "failed to find candidatepair IDs or stats for local: "+ lId +" remote: "+ rId);
       return;
     }
+
     info("checkStatsIceConnectionType verifying: local=" +
          JSON.stringify(lCand) + " remote=" + JSON.stringify(rCand));
-    if ((this.configuration) && (typeof this.configuration.iceServers !== 'undefined')) {
-      info("Ice Server configured");
-      // Note: the IP comparising is a workaround for bug 1097333
-      //       And this will fail if a TURN server address is a DNS name!
-      var serverIp = this.configuration.iceServers[0].url.split(':')[1];
-      ok(lCand.candidateType == "relayed" || rCand.candidateType == "relayed" ||
-         lCand.ipAddress === serverIp || rCand.ipAddress === serverIp,
-         "One peer uses a relay");
-    } else {
-      info("P2P configured");
-      ok(lCand.candidateType != "relayed" && rCand.candidateType != "relayed",
-         "Pure peer to peer call without a relay");
+    expectedLocalCandidateType = expectedLocalCandidateType || "host";
+    var candidateType = lCand.candidateType;
+    if ((lCand.mozLocalTransport === "tcp") && (candidateType === "relayed")) {
+      candidateType = "relayed-tcp";
     }
+
+    if ((expectedLocalCandidateType === "serverreflexive") &&
+        (candidateType === "peerreflexive")) {
+      // Be forgiving of prflx when expecting srflx, since that can happen due
+      // to timing.
+      candidateType = "serverreflexive";
+    }
+
+    is(candidateType,
+       expectedLocalCandidateType,
+       "Local candidate type is what we expected for selected pair");
   },
 
   /**
    * Compares amount of established ICE connection according to ICE candidate
    * pairs in the stats reporting with the expected amount of connection based
    * on the constraints.
    *
    * @param {object} stats
@@ -1840,16 +1854,65 @@ var scriptsReady = Promise.all([
   document.head.appendChild(el);
   return new Promise(r => { el.onload = r; el.onerror = r; });
 }));
 
 function createHTML(options) {
   return scriptsReady.then(() => realCreateHTML(options));
 }
 
-function runNetworkTest(testFunction) {
+var iceServerWebsocket;
+var iceServersArray = [];
+
+var setupIceServerConfig = useIceServer => {
+  // We disable ICE support for HTTP proxy when using a TURN server, because
+  // mochitest uses a fake HTTP proxy to serve content, which will eat our STUN
+  // packets for TURN TCP.
+  var enableHttpProxy = enable => new Promise(resolve => {
+    SpecialPowers.pushPrefEnv(
+        {'set': [['media.peerconnection.disable_http_proxy', !enable]]},
+        resolve);
+  });
+
+  var spawnIceServer = () => new Promise( (resolve, reject) => {
+    iceServerWebsocket = new WebSocket("ws://localhost:8191/");
+    iceServerWebsocket.onopen = (event) => {
+      info("websocket/process bridge open, starting ICE Server...");
+      iceServerWebsocket.send("iceserver");
+    }
+
+    iceServerWebsocket.onmessage = event => {
+      // The first message will contain the iceServers configuration, subsequent
+      // messages are just logging.
+      info("ICE Server: " + event.data);
+      resolve(event.data);
+    }
+
+    iceServerWebsocket.onerror = () => {
+      reject("ICE Server error: Is the ICE server websocket up?");
+    }
+
+    iceServerWebsocket.onclose = () => {
+      info("ICE Server websocket closed");
+      reject("ICE Server gone before getting configuration");
+    }
+  });
+
+  if (!useIceServer) {
+    info("Skipping ICE Server for this test");
+    return enableHttpProxy(true);
+  }
+
+  return enableHttpProxy(false)
+    .then(spawnIceServer)
+    .then(iceServersStr => { iceServersArray = JSON.parse(iceServersStr); });
+};
+
+function runNetworkTest(testFunction, fixtureOptions) {
+  fixtureOptions = fixtureOptions || {}
   return scriptsReady.then(() =>
     runTestWhenReady(options =>
       startNetworkAndTest()
+        .then(() => setupIceServerConfig(fixtureOptions.useIceServer))
         .then(() => testFunction(options))
     )
   );
 }
--- a/dom/media/tests/mochitest/templates.js
+++ b/dom/media/tests/mochitest/templates.js
@@ -436,23 +436,25 @@ var commandsPeerConnectionOfferAnswer = 
   function PC_REMOTE_CHECK_STATS(test) {
     return test.pcRemote.getStats().then(stats => {
       test.pcRemote.checkStats(stats, test.testOptions.steeplechase);
     });
   },
 
   function PC_LOCAL_CHECK_ICE_CONNECTION_TYPE(test) {
     return test.pcLocal.getStats().then(stats => {
-      test.pcLocal.checkStatsIceConnectionType(stats);
+      test.pcLocal.checkStatsIceConnectionType(stats,
+          test.testOptions.expectedLocalCandidateType);
     });
   },
 
   function PC_REMOTE_CHECK_ICE_CONNECTION_TYPE(test) {
     return test.pcRemote.getStats().then(stats => {
-      test.pcRemote.checkStatsIceConnectionType(stats);
+      test.pcRemote.checkStatsIceConnectionType(stats,
+          test.testOptions.expectedRemoteCandidateType);
     });
   },
 
   function PC_LOCAL_CHECK_ICE_CONNECTIONS(test) {
     return test.pcLocal.getStats().then(stats => {
       test.pcLocal.checkStatsIceConnections(stats,
                                             test._offer_constraints,
                                             test._offer_options,
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_basicAudioNATRelay.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="nonTrickleIce.js"></script>
+  <script type="application/javascript" src="pc.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1231975",
+    title: "Basic audio-only peer connection with port dependent NAT"
+  });
+
+  var test;
+  runNetworkTest(options => {
+    SpecialPowers.pushPrefEnv(
+      {
+        'set': [
+          ['media.peerconnection.nat_simulator.filtering_type', 'PORT_DEPENDENT'],
+          ['media.peerconnection.nat_simulator.mapping_type', 'PORT_DEPENDENT']
+        ]
+      }, function (options) {
+        options = options || {};
+        options.expectedLocalCandidateType = "serverreflexive";
+        options.expectedRemoteCandidateType = "relayed";
+        // If both have TURN, it is a toss-up which one will end up using a
+        // relay.
+        options.turn_disabled_local = true;
+        test = new PeerConnectionTest(options);
+        // Make sure we don't end up choosing the wrong thing due to delays in
+        // trickle. Once we are willing to accept trickle after ICE success, we
+        // can maybe wait a bit to allow things to stabilize.
+        // TODO(bug 1238249)
+        makeOffererNonTrickle(test.chain);
+        makeAnswererNonTrickle(test.chain);
+        test.setMediaConstraints([{audio: true}], [{audio: true}]);
+        test.run();
+      })
+  }, { useIceServer: true });
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_basicAudioNATRelayTCP.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="pc.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1231975",
+    title: "Basic audio-only peer connection with port dependent NAT that blocks UDP"
+  });
+
+  var test;
+  runNetworkTest(options => {
+    SpecialPowers.pushPrefEnv(
+      {
+        'set': [
+          ['media.peerconnection.nat_simulator.filtering_type', 'PORT_DEPENDENT'],
+          ['media.peerconnection.nat_simulator.mapping_type', 'PORT_DEPENDENT'],
+          ['media.peerconnection.nat_simulator.block_udp', true]
+        ]
+      }, function (options) {
+        options = options || {};
+        options.expectedLocalCandidateType = "relayed-tcp";
+        options.expectedRemoteCandidateType = "relayed-tcp";
+        // No reason to wait for gathering to complete like the other NAT tests,
+        // since relayed-tcp is the only thing that can work.
+        test = new PeerConnectionTest(options);
+        test.setMediaConstraints([{audio: true}], [{audio: true}]);
+        test.run();
+      })
+  }, { useIceServer: true });
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_basicAudioNATSrflx.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="nonTrickleIce.js"></script>
+  <script type="application/javascript" src="pc.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1231975",
+    title: "Basic audio-only peer connection with endpoint independent NAT"
+  });
+
+  var test;
+  runNetworkTest(options => {
+    SpecialPowers.pushPrefEnv(
+      {
+        'set': [
+          ['media.peerconnection.nat_simulator.filtering_type', 'ENDPOINT_INDEPENDENT'],
+          ['media.peerconnection.nat_simulator.mapping_type', 'ENDPOINT_INDEPENDENT']
+        ]
+      }, function (options) {
+        options = options || {};
+        options.expectedLocalCandidateType = "serverreflexive";
+        options.expectedRemoteCandidateType = "serverreflexive";
+        test = new PeerConnectionTest(options);
+        // Make sure we don't end up choosing the wrong thing due to delays in
+        // trickle. Once we are willing to accept trickle after ICE success, we
+        // can maybe wait a bit to allow things to stabilize.
+        // TODO(bug 1238249)
+        makeOffererNonTrickle(test.chain);
+        makeAnswererNonTrickle(test.chain);
+        test.setMediaConstraints([{audio: true}], [{audio: true}]);
+        test.run();
+      })
+  }, { useIceServer: true });
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/webaudio/AudioNodeEngine.cpp
+++ b/dom/media/webaudio/AudioNodeEngine.cpp
@@ -73,20 +73,17 @@ void AudioBufferAddWithScale(const float
 #ifdef BUILD_ARM_NEON
   if (mozilla::supports_neon()) {
     AudioBufferAddWithScale_NEON(aInput, aScale, aOutput, aSize);
     return;
   }
 #endif
 
 #ifdef USE_SSE2
-  // TODO: See Bug 1266112, we should either fix the source of the unaligned
-  //       buffers or do as much as possible with vector instructions and
-  //       fallback to scalar instructions where necessary.
-  if (mozilla::supports_sse2() && IS_ALIGNED16(aInput) && IS_ALIGNED16(aOutput)) {
+  if (mozilla::supports_sse2()) {
     AudioBufferAddWithScale_SSE(aInput, aScale, aOutput, aSize);
     return;
   }
 #endif
 
   if (aScale == 1.0f) {
     for (uint32_t i = 0; i < aSize; ++i) {
       aOutput[i] += aInput[i];
@@ -117,20 +114,17 @@ AudioBlockCopyChannelWithScale(const flo
 #ifdef BUILD_ARM_NEON
     if (mozilla::supports_neon()) {
       AudioBlockCopyChannelWithScale_NEON(aInput, aScale, aOutput);
       return;
     }
 #endif
 
 #ifdef USE_SSE2
-    // TODO: See Bug 1266112, we should either fix the source of the unaligned
-    //       buffers or do as much as possible with vector instructions and
-    //       fallback to scalar instructions where necessary.
-    if (mozilla::supports_sse2() && IS_ALIGNED16(aInput) && IS_ALIGNED16(aOutput)) {
+    if (mozilla::supports_sse2()) {
       AudioBlockCopyChannelWithScale_SSE(aInput, aScale, aOutput);
       return;
     }
 #endif
 
     for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
       aOutput[i] = aInput[i]*aScale;
     }
--- a/dom/network/TCPSocketChild.cpp
+++ b/dom/network/TCPSocketChild.cpp
@@ -122,16 +122,17 @@ TCPSocketChild::SendWindowlessOpenBind(n
                                 aUseSSL, true, mFilterName);
 }
 
 void
 TCPSocketChildBase::ReleaseIPDLReference()
 {
   MOZ_ASSERT(mIPCOpen);
   mIPCOpen = false;
+  mSocket = nullptr;
   this->Release();
 }
 
 void
 TCPSocketChildBase::AddIPDLReference()
 {
   MOZ_ASSERT(!mIPCOpen);
   mIPCOpen = true;
--- a/dom/network/TCPSocketParent.cpp
+++ b/dom/network/TCPSocketParent.cpp
@@ -335,17 +335,17 @@ TCPSocketParent::RecvData(const Sendable
       const nsCString& strData = aData.get_nsCString();
       mSocket->SendWithTrackingNumber(strData, aTrackingNumber, rv);
       break;
     }
 
     default:
       MOZ_CRASH("unexpected SendableData type");
   }
-  NS_ENSURE_FALSE(rv.Failed(), true);
+  NS_ENSURE_SUCCESS(rv.StealNSResult(), true);
   return true;
 }
 
 bool
 TCPSocketParent::RecvClose()
 {
   NS_ENSURE_TRUE(mSocket, true);
   mSocket->Close();
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -3373,17 +3373,18 @@ nsresult nsPluginHost::NewPluginURLStrea
 
   if (aURL.Length() <= 0)
     return NS_OK;
 
   // get the base URI for the plugin to create an absolute url
   // in case aURL is relative
   RefPtr<nsPluginInstanceOwner> owner = aInstance->GetOwner();
   if (owner) {
-    rv = NS_MakeAbsoluteURI(absUrl, aURL, nsCOMPtr<nsIURI>(owner->GetBaseURI()));
+    nsCOMPtr<nsIURI> baseURI = owner->GetBaseURI();
+    rv = NS_MakeAbsoluteURI(absUrl, aURL, baseURI);
   }
 
   if (absUrl.IsEmpty())
     absUrl.Assign(aURL);
 
   rv = NS_NewURI(getter_AddRefs(url), absUrl);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -99,17 +99,20 @@ nsPluginByteRangeStreamListener::OnStart
 
   nsCOMPtr<nsIStreamListener> finalStreamListener = do_QueryReferent(mWeakPtrPluginStreamListenerPeer);
   if (!finalStreamListener)
     return NS_ERROR_FAILURE;
 
   nsPluginStreamListenerPeer *pslp =
     static_cast<nsPluginStreamListenerPeer*>(finalStreamListener.get());
 
-  NS_ASSERTION(pslp->mRequests.IndexOfObject(GetBaseRequest(request)) != -1,
+#ifdef DEBUG
+  nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
+#endif
+  NS_ASSERTION(pslp->mRequests.IndexOfObject(baseRequest) != -1,
                "Untracked byte-range request?");
 
   nsCOMPtr<nsIStreamConverterService> serv = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
   if (NS_SUCCEEDED(rv)) {
     rv = serv->AsyncConvertData(MULTIPART_BYTERANGES,
                                 "*/*",
                                 finalStreamListener,
                                 nullptr,
@@ -426,17 +429,18 @@ nsPluginStreamListenerPeer::SetupPluginC
 NS_IMETHODIMP
 nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
                                            nsISupports* aContext)
 {
   nsresult rv = NS_OK;
   PROFILER_LABEL("nsPluginStreamListenerPeer", "OnStartRequest",
     js::ProfileEntry::Category::OTHER);
 
-  if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) {
+  nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
+  if (mRequests.IndexOfObject(baseRequest) == -1) {
     NS_ASSERTION(mRequests.Count() == 0,
                  "Only our initial stream should be unknown!");
     TrackRequest(request);
   }
 
   if (mHaveFiredOnStartRequest) {
     return NS_OK;
   }
@@ -883,17 +887,18 @@ nsPluginStreamListenerPeer::UseExistingP
 }
 
 NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
                                                           nsISupports* aContext,
                                                           nsIInputStream *aIStream,
                                                           uint64_t sourceOffset,
                                                           uint32_t aLength)
 {
-  if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) {
+  nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
+  if (mRequests.IndexOfObject(baseRequest) == -1) {
     MOZ_ASSERT(false, "Received OnDataAvailable for untracked request.");
     return NS_ERROR_UNEXPECTED;
   }
 
   if (mRequestFailed)
     return NS_ERROR_FAILURE;
 
   if (mAbort) {
--- a/dom/security/nsCSPParser.cpp
+++ b/dom/security/nsCSPParser.cpp
@@ -573,17 +573,18 @@ nsCSPParser::keywordSource()
 
   // Special case handling for 'self' which is not stored internally as a keyword,
   // but rather creates a nsCSPHostSrc using the selfURI
   if (CSP_IsKeyword(mCurToken, CSP_SELF)) {
     return CSP_CreateHostSrcFromURI(mSelfURI);
   }
 
   if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_INLINE)) {
-      nsCOMPtr<nsIDocument> doc = do_QueryReferent(mCSPContext->GetLoadingContext());
+      nsWeakPtr ctx = mCSPContext->GetLoadingContext();
+      nsCOMPtr<nsIDocument> doc = do_QueryReferent(ctx);
       if (doc) {
         doc->SetHasUnsafeInlineCSP(true);
       }
     // make sure script-src only contains 'unsafe-inline' once;
     // ignore duplicates and log warning
     if (mUnsafeInlineKeywordSrc) {
       const char16_t* params[] = { mCurToken.get() };
       logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringDuplicateSrc",
@@ -592,17 +593,18 @@ nsCSPParser::keywordSource()
     }
     // cache if we encounter 'unsafe-inline' so we can invalidate (ignore) it in
     // case that script-src directive also contains hash- or nonce-.
     mUnsafeInlineKeywordSrc = new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
     return mUnsafeInlineKeywordSrc;
   }
 
   if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_EVAL)) {
-    nsCOMPtr<nsIDocument> doc = do_QueryReferent(mCSPContext->GetLoadingContext());
+    nsWeakPtr ctx = mCSPContext->GetLoadingContext();
+    nsCOMPtr<nsIDocument> doc = do_QueryReferent(ctx);
     if (doc) {
       doc->SetHasUnsafeEvalCSP(true);
     }
     return new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
   }
   return nullptr;
 }
 
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -3248,23 +3248,16 @@ nsEditor::GetLeftmostChild(nsINode *aCur
     cur = next;
   }
 
   NS_NOTREACHED("What part of for(;;) do you not understand?");
   return nullptr;
 }
 
 bool
-nsEditor::IsBlockNode(nsIDOMNode* aNode)
-{
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  return IsBlockNode(node);
-}
-
-bool
 nsEditor::IsBlockNode(nsINode* aNode)
 {
   // stub to be overridden in nsHTMLEditor.
   // screwing around with the class hierarchy here in order
   // to not duplicate the code in GetNextNode/GetPrevNode
   // across both nsEditor/nsHTMLEditor.
   return false;
 }
@@ -3350,23 +3343,16 @@ nsEditor::IsDescendantOfRoot(nsINode* in
   NS_ENSURE_TRUE(inNode, false);
   nsCOMPtr<nsIContent> root = GetRoot();
   NS_ENSURE_TRUE(root, false);
 
   return nsContentUtils::ContentIsDescendantOf(inNode, root);
 }
 
 bool
-nsEditor::IsDescendantOfEditorRoot(nsIDOMNode* aNode)
-{
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  return IsDescendantOfEditorRoot(node);
-}
-
-bool
 nsEditor::IsDescendantOfEditorRoot(nsINode* aNode)
 {
   NS_ENSURE_TRUE(aNode, false);
   nsCOMPtr<nsIContent> root = GetEditorRoot();
   NS_ENSURE_TRUE(root, false);
 
   return nsContentUtils::ContentIsDescendantOf(aNode, root);
 }
@@ -3650,23 +3636,25 @@ nsEditor::GetChildAt(nsIDOMNode *aParent
   return resultNode;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // GetNodeAtRangeOffsetPoint: returns the node at this position in a range,
 // assuming that aParentOrNode is the node itself if it's a text node, or
 // the node's parent otherwise.
 //
-nsCOMPtr<nsIDOMNode>
+nsIContent*
 nsEditor::GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, int32_t aOffset)
 {
-  if (IsTextNode(aParentOrNode)) {
-    return aParentOrNode;
-  }
-  return GetChildAt(aParentOrNode, aOffset);
+  nsCOMPtr<nsINode> parentOrNode = do_QueryInterface(aParentOrNode);
+  NS_ENSURE_TRUE(parentOrNode || !aParentOrNode, nullptr);
+  if (parentOrNode->GetAsText()) {
+    return parentOrNode->AsContent();
+  }
+  return parentOrNode->GetChildAt(aOffset);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // GetStartNodeAndOffset: returns whatever the start parent & offset is of
 //                        the first range in the selection.
 nsresult
 nsEditor::GetStartNodeAndOffset(Selection* aSelection,
--- a/editor/libeditor/nsEditor.h
+++ b/editor/libeditor/nsEditor.h
@@ -138,16 +138,21 @@ inline bool operator!(const EditAction& 
  *  delegate the actual commands to the editor independent of the XPFE implementation.
  */
 class nsEditor : public nsIEditor,
                  public nsIEditorIMESupport,
                  public nsSupportsWeakReference,
                  public nsIPhonetic
 {
 public:
+  typedef mozilla::ErrorResult        ErrorResult;
+  typedef mozilla::dom::Element       Element;
+  typedef mozilla::dom::Selection     Selection;
+  typedef mozilla::dom::Text          Text;
+  template<typename T> using OwningNonNull = mozilla::OwningNonNull<T>;
 
   enum IterDirection
   {
     kIterForward,
     kIterBackward
   };
 
   /** The default constructor. This should suffice. the setting of the interfaces is done
@@ -194,90 +199,85 @@ public:
 
   virtual bool IsModifiableNode(nsINode *aNode);
 
   virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
                                   nsCOMPtr<nsINode>* aInOutNode,
                                   int32_t* aInOutOffset,
                                   nsIDocument* aDoc);
   nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
-                                      mozilla::dom::Text& aTextNode,
-                                      int32_t aOffset,
+                                      Text& aTextNode, int32_t aOffset,
                                       bool aSuppressIME = false);
   NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
                                  EStripWrappers aStripWrappers);
 
-  already_AddRefed<mozilla::dom::Element>
-  DeleteSelectionAndCreateElement(nsIAtom& aTag);
+  already_AddRefed<Element> DeleteSelectionAndCreateElement(nsIAtom& aTag);
 
   /* helper routines for node/parent manipulations */
   nsresult DeleteNode(nsINode* aNode);
   nsresult InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition);
   enum ECloneAttributes { eDontCloneAttributes, eCloneAttributes };
-  already_AddRefed<mozilla::dom::Element> ReplaceContainer(
-                            mozilla::dom::Element* aOldContainer,
-                            nsIAtom* aNodeType,
-                            nsIAtom* aAttribute = nullptr,
-                            const nsAString* aValue = nullptr,
-                            ECloneAttributes aCloneAttributes = eDontCloneAttributes);
-  void CloneAttributes(mozilla::dom::Element* aDest,
-                       mozilla::dom::Element* aSource);
+  already_AddRefed<Element> ReplaceContainer(Element* aOldContainer,
+                                             nsIAtom* aNodeType,
+                                             nsIAtom* aAttribute = nullptr,
+                                             const nsAString* aValue = nullptr,
+                                             ECloneAttributes aCloneAttributes
+                                             = eDontCloneAttributes);
+  void CloneAttributes(Element* aDest, Element* aSource);
 
   nsresult RemoveContainer(nsIContent* aNode);
-  already_AddRefed<mozilla::dom::Element> InsertContainerAbove(
-                                nsIContent* aNode,
-                                nsIAtom* aNodeType,
-                                nsIAtom* aAttribute = nullptr,
-                                const nsAString* aValue = nullptr);
+  already_AddRefed<Element> InsertContainerAbove(nsIContent* aNode,
+                                                 nsIAtom* aNodeType,
+                                                 nsIAtom* aAttribute = nullptr,
+                                                 const nsAString* aValue =
+                                                 nullptr);
   nsIContent* SplitNode(nsIContent& aNode, int32_t aOffset,
-                        mozilla::ErrorResult& aResult);
+                        ErrorResult& aResult);
   nsresult JoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
   nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset);
 
   /* Method to replace certain CreateElementNS() calls.
      Arguments:
       nsIAtom* aTag          - tag you want
   */
-  already_AddRefed<mozilla::dom::Element> CreateHTMLContent(nsIAtom* aTag);
+  already_AddRefed<Element> CreateHTMLContent(nsIAtom* aTag);
 
   // IME event handlers
   virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
   virtual nsresult UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent) = 0;
   void EndIMEComposition();
 
   void SwitchTextDirectionTo(uint32_t aDirection);
 
 protected:
   nsresult DetermineCurrentDirection();
   void FireInputEvent();
 
   /** Create a transaction for setting aAttribute to aValue on aElement.  Never
     * returns null.
     */
   already_AddRefed<mozilla::dom::ChangeAttributeTxn>
-  CreateTxnForSetAttribute(mozilla::dom::Element& aElement,
-                           nsIAtom& aAttribute, const nsAString& aValue);
+  CreateTxnForSetAttribute(Element& aElement, nsIAtom& aAttribute,
+                           const nsAString& aValue);
 
   /** Create a transaction for removing aAttribute on aElement.  Never returns
     * null.
     */
   already_AddRefed<mozilla::dom::ChangeAttributeTxn>
-  CreateTxnForRemoveAttribute(mozilla::dom::Element& aElement,
-                              nsIAtom& aAttribute);
+  CreateTxnForRemoveAttribute(Element& aElement, nsIAtom& aAttribute);
 
   /** create a transaction for creating a new child node of aParent of type aTag.
     */
   already_AddRefed<mozilla::dom::CreateElementTxn>
   CreateTxnForCreateElement(nsIAtom& aTag,
                             nsINode& aParent,
                             int32_t aPosition);
 
-  already_AddRefed<mozilla::dom::Element> CreateNode(nsIAtom* aTag,
-                                                     nsINode* aParent,
-                                                     int32_t aPosition);
+  already_AddRefed<Element> CreateNode(nsIAtom* aTag, nsINode* aParent,
+                                       int32_t aPosition);
 
   /** create a transaction for inserting aNode as a child of aParent.
     */
   already_AddRefed<mozilla::dom::InsertNodeTxn>
   CreateTxnForInsertNode(nsIContent& aNode, nsINode& aParent, int32_t aOffset);
 
   /** create a transaction for removing aNode from its parent.
     */
@@ -297,18 +297,18 @@ protected:
                                             int32_t* aOffset,
                                             int32_t* aLength);
 
 
   /** Create a transaction for inserting aStringToInsert into aTextNode.  Never
     * returns null.
     */
   already_AddRefed<mozilla::dom::InsertTextTxn>
-  CreateTxnForInsertText(const nsAString& aStringToInsert,
-                         mozilla::dom::Text& aTextNode, int32_t aOffset);
+  CreateTxnForInsertText(const nsAString& aStringToInsert, Text& aTextNode,
+                         int32_t aOffset);
 
   // Never returns null.
   already_AddRefed<mozilla::dom::IMETextTxn>
   CreateTxnForIMEText(const nsAString & aStringToInsert);
 
   /** create a transaction for adding a style sheet
     */
   NS_IMETHOD CreateTxnForAddStyleSheet(mozilla::StyleSheetHandle aSheet,
@@ -360,32 +360,30 @@ protected:
     eDocumentToBeDestroyed,
     eDocumentStateChanged
   } TDocumentListenerNotification;
 
   // tell the doc state listeners that the doc state has changed
   NS_IMETHOD NotifyDocumentListeners(TDocumentListenerNotification aNotificationType);
 
   /** make the given selection span the entire document */
-  virtual nsresult SelectEntireDocument(mozilla::dom::Selection* aSelection);
+  virtual nsresult SelectEntireDocument(Selection* aSelection);
 
   /** helper method for scrolling the selection into view after
    *  an edit operation. aScrollToAnchor should be true if you
    *  want to scroll to the point where the selection was started.
    *  If false, it attempts to scroll the end of the selection into view.
    *
    *  Editor methods *should* call this method instead of the versions
    *  in the various selection interfaces, since this version makes sure
    *  that the editor's sync/async settings for reflowing, painting, and
    *  scrolling match.
    */
   NS_IMETHOD ScrollSelectionIntoView(bool aScrollToAnchor);
 
-  // Convenience method; forwards to IsBlockNode(nsINode*).
-  bool IsBlockNode(nsIDOMNode* aNode);
   // stub.  see comment in source.
   virtual bool IsBlockNode(nsINode* aNode);
 
   // helper for GetPriorNode and GetNextNode
   nsIContent* FindNextLeafNode(nsINode  *aCurrentNode,
                                bool      aGoForward,
                                bool      bNoBlockCrossing);
 
@@ -426,18 +424,18 @@ public:
 
   /** All editor operations which alter the doc should be followed
    *  with a call to EndOperation */
   NS_IMETHOD EndOperation();
 
   /** routines for managing the preservation of selection across
    *  various editor actions */
   bool     ArePreservingSelection();
-  void     PreserveSelectionAcrossActions(mozilla::dom::Selection* aSel);
-  nsresult RestorePreservedSelection(mozilla::dom::Selection* aSel);
+  void     PreserveSelectionAcrossActions(Selection* aSel);
+  nsresult RestorePreservedSelection(Selection* aSel);
   void     StopPreservingSelection();
 
   /**
    * SplitNode() creates a new node identical to an existing node, and split
    * the contents between the two nodes
    * @param aExistingRightNode  The node to split.  It will become the new
    *                            node's next sibling.
    * @param aOffset             The offset of aExistingRightNode's
@@ -552,17 +550,16 @@ public:
   /** returns true if aNode is our root node */
   bool IsRoot(nsIDOMNode* inNode);
   bool IsRoot(nsINode* inNode);
   bool IsEditorRoot(nsINode* aNode);
 
   /** returns true if aNode is a descendant of our root node */
   bool IsDescendantOfRoot(nsIDOMNode* inNode);
   bool IsDescendantOfRoot(nsINode* inNode);
-  bool IsDescendantOfEditorRoot(nsIDOMNode* aNode);
   bool IsDescendantOfEditorRoot(nsINode* aNode);
 
   /** returns true if aNode is a container */
   virtual bool IsContainer(nsINode* aNode);
   virtual bool IsContainer(nsIDOMNode* aNode);
 
   /** returns true if aNode is an editable node */
   bool IsEditable(nsIDOMNode *aNode);
@@ -596,34 +593,35 @@ public:
 
   bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
   virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
 
   static bool IsTextNode(nsIDOMNode *aNode);
   static bool IsTextNode(nsINode *aNode);
 
   static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, int32_t aOffset);
-  static nsCOMPtr<nsIDOMNode> GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, int32_t aOffset);
+  static nsIContent* GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode,
+                                               int32_t aOffset);
 
-  static nsresult GetStartNodeAndOffset(mozilla::dom::Selection* aSelection,
+  static nsresult GetStartNodeAndOffset(Selection* aSelection,
                                         nsIDOMNode** outStartNode,
                                         int32_t* outStartOffset);
-  static nsresult GetStartNodeAndOffset(mozilla::dom::Selection* aSelection,
+  static nsresult GetStartNodeAndOffset(Selection* aSelection,
                                         nsINode** aStartNode,
                                         int32_t* aStartOffset);
-  static nsresult GetEndNodeAndOffset(mozilla::dom::Selection* aSelection,
+  static nsresult GetEndNodeAndOffset(Selection* aSelection,
                                       nsIDOMNode** outEndNode,
                                       int32_t* outEndOffset);
-  static nsresult GetEndNodeAndOffset(mozilla::dom::Selection* aSelection,
+  static nsresult GetEndNodeAndOffset(Selection* aSelection,
                                       nsINode** aEndNode,
                                       int32_t* aEndOffset);
 #if DEBUG_JOE
   static void DumpNode(nsIDOMNode *aNode, int32_t indent=0);
 #endif
-  mozilla::dom::Selection* GetSelection(int16_t aSelectionType =
+  Selection* GetSelection(int16_t aSelectionType =
       nsISelectionController::SELECTION_NORMAL);
 
   // Helpers to add a node to the selection.
   // Used by table cell selection methods
   nsresult CreateRange(nsIDOMNode *aStartParent, int32_t aStartOffset,
                        nsIDOMNode *aEndParent, int32_t aEndOffset,
                        nsRange** aRange);
 
@@ -648,36 +646,36 @@ public:
   void BeginUpdateViewBatch(void);
   virtual nsresult EndUpdateViewBatch(void);
 
   bool GetShouldTxnSetSelection();
 
   virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
 
   nsresult HandleInlineSpellCheck(EditAction action,
-                                  mozilla::dom::Selection* aSelection,
+                                  Selection* aSelection,
                                     nsIDOMNode *previousSelectedNode,
                                     int32_t previousSelectedOffset,
                                     nsIDOMNode *aStartNode,
                                     int32_t aStartOffset,
                                     nsIDOMNode *aEndNode,
                                     int32_t aEndOffset);
 
   virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() = 0;
 
   // Fast non-refcounting editor root element accessor
-  mozilla::dom::Element *GetRoot();
+  Element* GetRoot();
 
   // Likewise, but gets the editor's root instead, which is different for HTML
   // editors
-  virtual mozilla::dom::Element* GetEditorRoot();
+  virtual Element* GetEditorRoot();
 
   // Likewise, but gets the text control element instead of the root for
   // plaintext editors
-  mozilla::dom::Element* GetExposedRoot();
+  Element* GetExposedRoot();
 
   // Accessor methods to flags
   bool IsPlaintextEditor() const
   {
     return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
   }
 
   bool IsSingleLineEditor() const
@@ -830,37 +828,37 @@ protected:
     eTriTrue
   };
   // Spellchecking
   nsCString mContentMIMEType;       // MIME type of the doc we are editing.
 
   nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
 
   RefPtr<nsTransactionManager> mTxnMgr;
-  nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
-  RefPtr<mozilla::dom::Text>    mIMETextNode; // current IME text node
+  nsCOMPtr<Element> mRootElement; // cached root node
+  RefPtr<Text>    mIMETextNode; // current IME text node
   nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; // The form field as an event receiver
   nsCOMPtr<nsIDOMEventListener> mEventListener;
   nsWeakPtr        mSelConWeak;          // weak reference to the nsISelectionController
   nsWeakPtr        mPlaceHolderTxn;      // weak reference to placeholder for begin/end batch purposes
   nsWeakPtr        mDocWeak;             // weak reference to the nsIDOMDocument
   nsIAtom          *mPlaceHolderName;    // name of placeholder transaction
   nsSelectionState *mSelState;           // saved selection state for placeholder txn batching
   nsString         *mPhonetic;
   // IME composition this is not null between compositionstart and
   // compositionend.
   RefPtr<mozilla::TextComposition> mComposition;
 
   // various listeners
   // Listens to all low level actions on the doc
-  nsTArray<mozilla::OwningNonNull<nsIEditActionListener>> mActionListeners;
+  nsTArray<OwningNonNull<nsIEditActionListener>> mActionListeners;
   // Just notify once per high level change
-  nsTArray<mozilla::OwningNonNull<nsIEditorObserver>> mEditorObservers;
+  nsTArray<OwningNonNull<nsIEditorObserver>> mEditorObservers;
   // Listen to overall doc state (dirty or not, just created, etc)
-  nsTArray<mozilla::OwningNonNull<nsIDocumentStateListener>> mDocStateListeners;
+  nsTArray<OwningNonNull<nsIDocumentStateListener>> mDocStateListeners;
 
   nsSelectionState  mSavedSel;           // cached selection for nsAutoSelectionReset
   nsRangeUpdater    mRangeUpdater;       // utility class object for maintaining preserved ranges
 
   uint32_t          mModCount;     // number of modifications (for undo/redo stack)
   uint32_t          mFlags;        // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
 
   int32_t           mUpdateCount;
--- a/editor/libeditor/nsEditorEventListener.cpp
+++ b/editor/libeditor/nsEditorEventListener.cpp
@@ -319,17 +319,21 @@ nsEditorEventListener::GetFocusedRootCon
   nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContent();
   if (!focusedContent) {
     return nullptr;
   }
 
   nsIDocument* composedDoc = focusedContent->GetComposedDoc();
   NS_ENSURE_TRUE(composedDoc, nullptr);
 
-  return composedDoc->HasFlag(NODE_IS_EDITABLE) ? nullptr : focusedContent;
+  if (composedDoc->HasFlag(NODE_IS_EDITABLE)) {
+    return nullptr;
+  }
+
+  return focusedContent;
 }
 
 bool
 nsEditorEventListener::EditorHasFocus()
 {
   NS_PRECONDITION(mEditor,
     "The caller must check whether this is connected to an editor");
   nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContent();
--- a/editor/libeditor/nsHTMLAbsPosition.cpp
+++ b/editor/libeditor/nsHTMLAbsPosition.cpp
@@ -78,38 +78,34 @@ nsHTMLEditor::AbsolutePositionSelection(
     return res;
 
   return mRules->DidDoAction(selection, &ruleInfo, res);
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval)
 {
-  nsCOMPtr<nsIDOMElement> element;
-  nsresult res = GetSelectionContainer(getter_AddRefs(element));
-  NS_ENSURE_SUCCESS(res, res);
-
   nsAutoString positionStr;
-  nsCOMPtr<nsINode> node = do_QueryInterface(element);
+  nsCOMPtr<nsINode> node = GetSelectionContainer();
   nsCOMPtr<nsIDOMNode> resultNode;
 
   while (!resultNode && node && !node->IsHTMLElement(nsGkAtoms::html)) {
-    res = mHTMLCSSUtils->GetComputedProperty(*node, *nsGkAtoms::position,
-                                             positionStr);
+    nsresult res =
+      mHTMLCSSUtils->GetComputedProperty(*node, *nsGkAtoms::position,
+                                         positionStr);
     NS_ENSURE_SUCCESS(res, res);
     if (positionStr.EqualsLiteral("absolute"))
       resultNode = GetAsDOMNode(node);
     else {
       node = node->GetParentNode();
     }
   }
 
-  element = do_QueryInterface(resultNode );
-  *_retval = element;
-  NS_IF_ADDREF(*_retval);
+  nsCOMPtr<nsIDOMElement> element = do_QueryInterface(resultNode);
+  element.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::GetSelectionContainerAbsolutelyPositioned(bool *aIsSelectionContainerAbsolutelyPositioned)
 {
   *aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nullptr);
   return NS_OK;
--- a/editor/libeditor/nsHTMLAnonymousUtils.cpp
+++ b/editor/libeditor/nsHTMLAnonymousUtils.cpp
@@ -143,18 +143,18 @@ nsHTMLEditor::CreateAnonymousElement(con
   nsCOMPtr<nsIDocument> doc = GetDocument();
   NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER);
 
   // Get the pres shell
   nsCOMPtr<nsIPresShell> ps = GetPresShell();
   NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
 
   // Create a new node through the element factory
-  nsCOMPtr<Element> newContent =
-    CreateHTMLContent(nsCOMPtr<nsIAtom>(NS_Atomize(aTag)));
+  nsCOMPtr<nsIAtom> tagAtom = NS_Atomize(aTag);
+  nsCOMPtr<Element> newContent = CreateHTMLContent(tagAtom);
   NS_ENSURE_STATE(newContent);
 
   nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newContent);
   NS_ENSURE_TRUE(newElement, NS_ERROR_FAILURE);
 
   // add the "hidden" class if needed
   nsresult res;
   if (aIsCreatedHidden) {
--- a/editor/libeditor/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/nsHTMLDataTransfer.cpp
@@ -339,18 +339,17 @@ nsHTMLEditor::DoInsertHTMLWithContext(co
 
   if (!cellSelectionMode)
   {
     rv = DeleteSelectionAndPrepareToCreateNode();
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aClearStyle) {
       // pasting does not inherit local inline styles
-      nsCOMPtr<nsIDOMNode> tmpNode =
-        do_QueryInterface(selection->GetAnchorNode());
+      nsCOMPtr<nsINode> tmpNode = selection->GetAnchorNode();
       int32_t tmpOffset = static_cast<int32_t>(selection->AnchorOffset());
       rv = ClearStyle(address_of(tmpNode), &tmpOffset, nullptr, nullptr);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
   else
   {
     // delete whole cells: we will replace with new table content
@@ -377,18 +376,18 @@ nsHTMLEditor::DoInsertHTMLWithContext(co
   {
     // The rules code (WillDoAction above) might have changed the selection.
     // refresh our memory...
     rv = GetStartNodeAndOffset(selection, getter_AddRefs(parentNode), &offsetOfNewNode);
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(parentNode, NS_ERROR_FAILURE);
 
     // Adjust position based on the first node we are going to insert.
-    NormalizeEOLInsertPosition(GetAsDOMNode(nodeList[0]),
-                               address_of(parentNode), &offsetOfNewNode);
+    NormalizeEOLInsertPosition(nodeList[0], address_of(parentNode),
+                               &offsetOfNewNode);
 
     // if there are any invisible br's after our insertion point, remove them.
     // this is because if there is a br at end of what we paste, it will make
     // the invisible br visible.
     nsWSRunObject wsObj(this, parentNode, offsetOfNewNode);
     if (wsObj.mEndReasonNode &&
         nsTextEditUtils::IsBreak(wsObj.mEndReasonNode) &&
         !IsVisBreak(wsObj.mEndReasonNode)) {
@@ -452,17 +451,19 @@ nsHTMLEditor::DoInsertHTMLWithContext(co
       ReplaceOrphanedStructure(StartOrEnd::end, nodeList,
                                endListAndTableArray, highWaterMark);
     }
 
     // Loop over the node list and paste the nodes:
     nsCOMPtr<nsIDOMNode> parentBlock, lastInsertNode, insertedContextParent;
     int32_t listCount = nodeList.Length();
     int32_t j;
-    if (IsBlockNode(parentNode))
+    nsCOMPtr<nsINode> parentNodeNode = do_QueryInterface(parentNode);
+    NS_ENSURE_STATE(parentNodeNode || !parentNode);
+    if (IsBlockNode(parentNodeNode))
       parentBlock = parentNode;
     else
       parentBlock = GetBlockNodeParent(parentNode);
 
     for (j=0; j<listCount; j++)
     {
       bool bDidInsert = false;
       nsCOMPtr<nsIDOMNode> curNode = nodeList[j]->AsDOMNode();
--- a/editor/libeditor/nsHTMLEditRules.cpp
+++ b/editor/libeditor/nsHTMLEditRules.cpp
@@ -70,24 +70,22 @@ enum
   kNextSib = 2,
   kBothSibs = 3
 };
 
 /********************************************************
  *  first some helpful functors we will use
  ********************************************************/
 
-static bool IsBlockNode(nsIDOMNode* node)
-{
-  bool isBlock (false);
-  nsHTMLEditor::NodeIsBlockStatic(node, &isBlock);
-  return isBlock;
-}
-
-static bool IsInlineNode(nsIDOMNode* node)
+static bool IsBlockNode(const nsINode& node)
+{
+  return nsHTMLEditor::NodeIsBlockStatic(&node);
+}
+
+static bool IsInlineNode(const nsINode& node)
 {
   return !IsBlockNode(node);
 }
 
 static bool
 IsStyleCachePreservingAction(EditAction action)
 {
   return action == EditAction::deleteSelection ||
@@ -130,17 +128,17 @@ class nsBRNodeFunctor : public nsBoolDom
 class nsEmptyEditableFunctor : public nsBoolDomIterFunctor
 {
   public:
     explicit nsEmptyEditableFunctor(nsHTMLEditor* editor) : mHTMLEditor(editor) {}
     virtual bool operator()(nsINode* aNode) const
     {
       if (mHTMLEditor->IsEditable(aNode) &&
           (nsHTMLEditUtils::IsListItem(aNode) ||
-           nsHTMLEditUtils::IsTableCellOrCaption(GetAsDOMNode(aNode)))) {
+           nsHTMLEditUtils::IsTableCellOrCaption(*aNode))) {
         bool bIsEmptyNode;
         nsresult res = mHTMLEditor->IsEmptyNode(aNode, &bIsEmptyNode, false, false);
         NS_ENSURE_SUCCESS(res, false);
         if (bIsEmptyNode)
           return true;
       }
       return false;
     }
@@ -307,128 +305,133 @@ nsHTMLEditRules::DetachEditor()
   mHTMLEditor = nullptr;
   return nsTextEditRules::DetachEditor();
 }
 
 NS_IMETHODIMP
 nsHTMLEditRules::BeforeEdit(EditAction action,
                             nsIEditor::EDirection aDirection)
 {
-  if (mLockRulesSniffing) return NS_OK;
-
-  nsAutoLockRulesSniffing lockIt((nsTextEditRules*)this);
+  if (mLockRulesSniffing) {
+    return NS_OK;
+  }
+
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  nsAutoLockRulesSniffing lockIt(this);
   mDidExplicitlySetInterline = false;
 
-  if (!mActionNesting++)
-  {
-    // clear our flag about if just deleted a range
+  if (!mActionNesting) {
+    mActionNesting++;
+
+    // Clear our flag about if just deleted a range
     mDidRangedDelete = false;
 
-    // remember where our selection was before edit action took place:
-
-    // get selection
-    NS_ENSURE_STATE(mHTMLEditor);
+    // Remember where our selection was before edit action took place:
+
+    // Get selection
     RefPtr<Selection> selection = mHTMLEditor->GetSelection();
 
-    // get the selection location
+    // Get the selection location
     if (!selection->RangeCount()) {
       return NS_ERROR_UNEXPECTED;
     }
     mRangeItem->startNode = selection->GetRangeAt(0)->GetStartParent();
     mRangeItem->startOffset = selection->GetRangeAt(0)->StartOffset();
     mRangeItem->endNode = selection->GetRangeAt(0)->GetEndParent();
     mRangeItem->endOffset = selection->GetRangeAt(0)->EndOffset();
-    nsCOMPtr<nsIDOMNode> selStartNode = GetAsDOMNode(mRangeItem->startNode);
-    nsCOMPtr<nsIDOMNode> selEndNode = GetAsDOMNode(mRangeItem->endNode);
-
-    // register this range with range updater to track this as we perturb the doc
-    NS_ENSURE_STATE(mHTMLEditor);
+    nsCOMPtr<nsINode> selStartNode = mRangeItem->startNode;
+    nsCOMPtr<nsINode> selEndNode = mRangeItem->endNode;
+
+    // Register with range updater to track this as we perturb the doc
     (mHTMLEditor->mRangeUpdater).RegisterRangeItem(mRangeItem);
 
-    // clear deletion state bool
+    // Clear deletion state bool
     mDidDeleteSelection = false;
 
-    // clear out mDocChangeRange and mUtilRange
-    if(mDocChangeRange)
-    {
-      // clear out our accounting of what changed
+    // Clear out mDocChangeRange and mUtilRange
+    if (mDocChangeRange) {
+      // Clear out our accounting of what changed
       mDocChangeRange->Reset();
     }
-    if(mUtilRange)
-    {
-      // ditto for mUtilRange.
+    if (mUtilRange) {
+      // Ditto for mUtilRange.
       mUtilRange->Reset();
     }
 
-    // remember current inline styles for deletion and normal insertion operations
+    // Remember current inline styles for deletion and normal insertion ops
     if (action == EditAction::insertText ||
         action == EditAction::insertIMEText ||
         action == EditAction::deleteSelection ||
         IsStyleCachePreservingAction(action)) {
-      nsCOMPtr<nsIDOMNode> selNode = selStartNode;
-      if (aDirection == nsIEditor::eNext)
-        selNode = selEndNode;
-      nsresult res = CacheInlineStyles(selNode);
-      NS_ENSURE_SUCCESS(res, res);
+      nsCOMPtr<nsINode> selNode =
+        aDirection == nsIEditor::eNext ? selEndNode : selStartNode;
+      nsresult rv = CacheInlineStyles(GetAsDOMNode(selNode));
+      NS_ENSURE_SUCCESS(rv, rv);
     }
 
     // Stabilize the document against contenteditable count changes
-    NS_ENSURE_STATE(mHTMLEditor);
     nsCOMPtr<nsIDOMDocument> doc = mHTMLEditor->GetDOMDocument();
     NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
     NS_ENSURE_TRUE(htmlDoc, NS_ERROR_FAILURE);
     if (htmlDoc->GetEditingState() == nsIHTMLDocument::eContentEditable) {
       htmlDoc->ChangeContentEditableCount(nullptr, +1);
       mRestoreContentEditableCount = true;
     }
 
-    // check that selection is in subtree defined by body node
+    // Check that selection is in subtree defined by body node
     ConfirmSelectionInBody();
-    // let rules remember the top level action
+    // Let rules remember the top level action
     mTheAction = action;
   }
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsHTMLEditRules::AfterEdit(EditAction action,
                            nsIEditor::EDirection aDirection)
 {
-  if (mLockRulesSniffing) return NS_OK;
+  if (mLockRulesSniffing) {
+    return NS_OK;
+  }
+
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
 
   nsAutoLockRulesSniffing lockIt(this);
 
-  NS_PRECONDITION(mActionNesting>0, "bad action nesting!");
-  nsresult res = NS_OK;
-  if (!--mActionNesting)
-  {
-    // do all the tricky stuff
-    res = AfterEditInner(action, aDirection);
-
-    // free up selectionState range item
-    NS_ENSURE_STATE(mHTMLEditor);
+  MOZ_ASSERT(mActionNesting > 0);
+  nsresult rv = NS_OK;
+  mActionNesting--;
+  if (!mActionNesting) {
+    // Do all the tricky stuff
+    rv = AfterEditInner(action, aDirection);
+
+    // Free up selectionState range item
     (mHTMLEditor->mRangeUpdater).DropRangeItem(mRangeItem);
 
     // Reset the contenteditable count to its previous value
     if (mRestoreContentEditableCount) {
-      NS_ENSURE_STATE(mHTMLEditor);
       nsCOMPtr<nsIDOMDocument> doc = mHTMLEditor->GetDOMDocument();
       NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
       nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
       NS_ENSURE_TRUE(htmlDoc, NS_ERROR_FAILURE);
       if (htmlDoc->GetEditingState() == nsIHTMLDocument::eContentEditable) {
         htmlDoc->ChangeContentEditableCount(nullptr, -1);
       }
       mRestoreContentEditableCount = false;
     }
   }
 
-  return res;
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
 }
 
 
 nsresult
 nsHTMLEditRules::AfterEditInner(EditAction action,
                                 nsIEditor::EDirection aDirection)
 {
   ConfirmSelectionInBody();
@@ -560,20 +563,20 @@ nsHTMLEditRules::AfterEditInner(EditActi
   // detect empty doc
   res = CreateBogusNodeIfNeeded(selection);
 
   // adjust selection HINT if needed
   NS_ENSURE_SUCCESS(res, res);
 
   if (!mDidExplicitlySetInterline)
   {
-    res = CheckInterlinePosition(selection);
-  }
-
-  return res;
+    CheckInterlinePosition(*selection);
+  }
+
+  return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsHTMLEditRules::WillDoAction(Selection* aSelection,
                               nsRulesInfo* aInfo,
                               bool* aCancel,
                               bool* aHandled)
@@ -640,25 +643,26 @@ nsHTMLEditRules::WillDoAction(Selection*
       return WillDeleteSelection(aSelection, info->collapsedAction,
                                  info->stripWrappers, aCancel, aHandled);
     case EditAction::makeList:
       return WillMakeList(aSelection, info->blockType, info->entireList,
                           info->bulletType, aCancel, aHandled);
     case EditAction::indent:
       return WillIndent(aSelection, aCancel, aHandled);
     case EditAction::outdent:
-      return WillOutdent(aSelection, aCancel, aHandled);
+      return WillOutdent(*aSelection, aCancel, aHandled);
     case EditAction::setAbsolutePosition:
-      return WillAbsolutePosition(aSelection, aCancel, aHandled);
+      return WillAbsolutePosition(*aSelection, aCancel, aHandled);
     case EditAction::removeAbsolutePosition:
       return WillRemoveAbsolutePosition(aSelection, aCancel, aHandled);
     case EditAction::align:
-      return WillAlign(aSelection, info->alignType, aCancel, aHandled);
+      return WillAlign(*aSelection, *info->alignType, aCancel, aHandled);
     case EditAction::makeBasicBlock:
-      return WillMakeBasicBlock(aSelection, info->blockType, aCancel, aHandled);
+      return WillMakeBasicBlock(*aSelection, *info->blockType, aCancel,
+                                aHandled);
     case EditAction::removeList:
       return WillRemoveList(aSelection, info->bOrdered, aCancel, aHandled);
     case EditAction::makeDefListItem:
       return WillMakeDefListItem(aSelection, info->blockType, info->entireList,
                                  aCancel, aHandled);
     case EditAction::insertElement:
       WillInsert(*aSelection, aCancel);
       return NS_OK;
@@ -788,175 +792,149 @@ nsHTMLEditRules::GetListItemState(bool *
 
   // hokey arithmetic with booleans
   if ( (*aDT + *aDD + bNonList) > 1) *aMixed = true;
 
   return NS_OK;
 }
 
 nsresult
-nsHTMLEditRules::GetAlignment(bool *aMixed, nsIHTMLEditor::EAlignment *aAlign)
-{
-  // for now, just return first alignment.  we'll lie about
-  // if it's mixed.  This is for efficiency
-  // given that our current ui doesn't care if it's mixed.
-  // cmanske: NOT TRUE! We would like to pay attention to mixed state
-  //  in Format | Align submenu!
-
-  // this routine assumes that alignment is done ONLY via divs
-
-  // default alignment is left
-  NS_ENSURE_TRUE(aMixed && aAlign, NS_ERROR_NULL_POINTER);
+nsHTMLEditRules::GetAlignment(bool* aMixed, nsIHTMLEditor::EAlignment* aAlign)
+{
+  MOZ_ASSERT(aMixed && aAlign);
+
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  // For now, just return first alignment.  We'll lie about if it's mixed.
+  // This is for efficiency given that our current ui doesn't care if it's
+  // mixed.
+  // cmanske: NOT TRUE! We would like to pay attention to mixed state in Format
+  // | Align submenu!
+
+  // This routine assumes that alignment is done ONLY via divs
+
+  // Default alignment is left
   *aMixed = false;
   *aAlign = nsIHTMLEditor::eLeft;
 
-  // get selection
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<Selection> selection = mHTMLEditor->GetSelection();
-  NS_ENSURE_STATE(selection);
-
-  // get selection location
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsCOMPtr<Element> rootElem = mHTMLEditor->GetRoot();
-  NS_ENSURE_TRUE(rootElem, NS_ERROR_FAILURE);
-
-  int32_t offset, rootOffset;
-  nsCOMPtr<nsINode> parent = nsEditor::GetNodeLocation(rootElem, &rootOffset);
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsresult res = mHTMLEditor->GetStartNodeAndOffset(selection,
-                                                    getter_AddRefs(parent),
-                                                    &offset);
-  NS_ENSURE_SUCCESS(res, res);
-
-  // is the selection collapsed?
+  // Get selection
+  NS_ENSURE_STATE(mHTMLEditor->GetSelection());
+  OwningNonNull<Selection> selection = *mHTMLEditor->GetSelection();
+
+  // Get selection location
+  NS_ENSURE_TRUE(mHTMLEditor->GetRoot(), NS_ERROR_FAILURE);
+  OwningNonNull<Element> root = *mHTMLEditor->GetRoot();
+
+  int32_t rootOffset = root->GetParentNode() ?
+                       root->GetParentNode()->IndexOf(root) : -1;
+
+  NS_ENSURE_STATE(selection->GetRangeAt(0) &&
+                  selection->GetRangeAt(0)->GetStartParent());
+  OwningNonNull<nsINode> parent = *selection->GetRangeAt(0)->GetStartParent();
+  int32_t offset = selection->GetRangeAt(0)->StartOffset();
+
+  // Is the selection collapsed?
   nsCOMPtr<nsINode> nodeToExamine;
-  if (selection->Collapsed()) {
-    // if it is, we want to look at 'parent' and its ancestors
-    // for divs with alignment on them
-    nodeToExamine = parent;
-  }
-  else if (!mHTMLEditor) {
-    return NS_ERROR_UNEXPECTED;
-  }
-  else if (mHTMLEditor->IsTextNode(parent))
-  {
-    // if we are in a text node, then that is the node of interest
+  if (selection->Collapsed() || parent->GetAsText()) {
+    // If selection is collapsed, we want to look at 'parent' and its ancestors
+    // for divs with alignment on them.  If we are in a text node, then that is
+    // the node of interest.
     nodeToExamine = parent;
   } else if (parent->IsHTMLElement(nsGkAtoms::html) && offset == rootOffset) {
-    // if we have selected the body, let's look at the first editable node
-    NS_ENSURE_STATE(mHTMLEditor);
+    // If we have selected the body, let's look at the first editable node
     nodeToExamine = mHTMLEditor->GetNextNode(parent, offset, true);
-  }
-  else
-  {
+  } else {
     nsTArray<RefPtr<nsRange>> arrayOfRanges;
-    GetPromotedRanges(*selection, arrayOfRanges, EditAction::align);
-
-    // use these ranges to construct a list of nodes to act on.
+    GetPromotedRanges(selection, arrayOfRanges, EditAction::align);
+
+    // Use these ranges to construct a list of nodes to act on.
     nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
-    res = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
-                               EditAction::align, TouchContent::no);
-    NS_ENSURE_SUCCESS(res, res);
+    nsresult rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
+                                       EditAction::align, TouchContent::no);
+    NS_ENSURE_SUCCESS(rv, rv);
     nodeToExamine = arrayOfNodes.SafeElementAt(0);
   }
 
   NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
 
   NS_NAMED_LITERAL_STRING(typeAttrName, "align");
-  nsIAtom  *dummyProperty = nullptr;
-  NS_ENSURE_STATE(mHTMLEditor);
   nsCOMPtr<Element> blockParent = mHTMLEditor->GetBlock(*nodeToExamine);
 
   NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  if (mHTMLEditor->IsCSSEnabled())
-  {
-    NS_ENSURE_STATE(mHTMLEditor);
-    if (mHTMLEditor->mHTMLCSSUtils->IsCSSEditableProperty(blockParent,
-                                                          dummyProperty,
-                                                          &typeAttrName)) {
-      // we are in CSS mode and we know how to align this element with CSS
-      nsAutoString value;
-      // let's get the value(s) of text-align or margin-left/margin-right
-      NS_ENSURE_STATE(mHTMLEditor);
-      mHTMLEditor->mHTMLCSSUtils->GetCSSEquivalentToHTMLInlineStyleSet(
-        blockParent, dummyProperty, &typeAttrName, value,
-        nsHTMLCSSUtils::eComputed);
-      if (value.EqualsLiteral("center") ||
-          value.EqualsLiteral("-moz-center") ||
-          value.EqualsLiteral("auto auto"))
-      {
-        *aAlign = nsIHTMLEditor::eCenter;
-        return NS_OK;
-      }
-      if (value.EqualsLiteral("right") ||
-          value.EqualsLiteral("-moz-right") ||
-          value.EqualsLiteral("auto 0px"))
-      {
-        *aAlign = nsIHTMLEditor::eRight;
-        return NS_OK;
-      }
-      if (value.EqualsLiteral("justify"))
-      {
-        *aAlign = nsIHTMLEditor::eJustify;
-        return NS_OK;
-      }
-      *aAlign = nsIHTMLEditor::eLeft;
+  if (mHTMLEditor->IsCSSEnabled() &&
+      mHTMLEditor->mHTMLCSSUtils->IsCSSEditableProperty(blockParent, nullptr,
+                                                        &typeAttrName)) {
+    // We are in CSS mode and we know how to align this element with CSS
+    nsAutoString value;
+    // Let's get the value(s) of text-align or margin-left/margin-right
+    mHTMLEditor->mHTMLCSSUtils->GetCSSEquivalentToHTMLInlineStyleSet(
+        blockParent, nullptr, &typeAttrName, value, nsHTMLCSSUtils::eComputed);
+    if (value.EqualsLiteral("center") ||
+        value.EqualsLiteral("-moz-center") ||
+        value.EqualsLiteral("auto auto")) {
+      *aAlign = nsIHTMLEditor::eCenter;
       return NS_OK;
     }
-  }
-
-  // check up the ladder for divs with alignment
+    if (value.EqualsLiteral("right") ||
+        value.EqualsLiteral("-moz-right") ||
+        value.EqualsLiteral("auto 0px")) {
+      *aAlign = nsIHTMLEditor::eRight;
+      return NS_OK;
+    }
+    if (value.EqualsLiteral("justify")) {
+      *aAlign = nsIHTMLEditor::eJustify;
+      return NS_OK;
+    }
+    *aAlign = nsIHTMLEditor::eLeft;
+    return NS_OK;
+  }
+
+  // Check up the ladder for divs with alignment
   bool isFirstNodeToExamine = true;
-  while (nodeToExamine)
-  {
-    if (!isFirstNodeToExamine && nsHTMLEditUtils::IsTable(nodeToExamine))
-    {
-      // the node to examine is a table and this is not the first node
-      // we examine; let's break here to materialize the 'inline-block'
-      // behaviour of html tables regarding to text alignment
+  for (; nodeToExamine; nodeToExamine = nodeToExamine->GetParentNode()) {
+    if (!isFirstNodeToExamine &&
+        nodeToExamine->IsHTMLElement(nsGkAtoms::table)) {
+      // The node to examine is a table and this is not the first node we
+      // examine; let's break here to materialize the 'inline-block' behaviour
+      // of html tables regarding to text alignment
       return NS_OK;
     }
     if (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(nodeToExamine))) {
-      // check for alignment
-      nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(nodeToExamine);
-      if (elem)
-      {
-        nsAutoString typeAttrVal;
-        res = elem->GetAttribute(NS_LITERAL_STRING("align"), typeAttrVal);
-        ToLowerCase(typeAttrVal);
-        if (NS_SUCCEEDED(res) && typeAttrVal.Length())
-        {
-          if (typeAttrVal.EqualsLiteral("center"))
-            *aAlign = nsIHTMLEditor::eCenter;
-          else if (typeAttrVal.EqualsLiteral("right"))
-            *aAlign = nsIHTMLEditor::eRight;
-          else if (typeAttrVal.EqualsLiteral("justify"))
-            *aAlign = nsIHTMLEditor::eJustify;
-          else
-            *aAlign = nsIHTMLEditor::eLeft;
-          return res;
+      // Check for alignment
+      nsAutoString typeAttrVal;
+      nodeToExamine->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::align,
+                                          typeAttrVal);
+      ToLowerCase(typeAttrVal);
+      if (!typeAttrVal.IsEmpty()) {
+        if (typeAttrVal.EqualsLiteral("center")) {
+          *aAlign = nsIHTMLEditor::eCenter;
+        } else if (typeAttrVal.EqualsLiteral("right")) {
+          *aAlign = nsIHTMLEditor::eRight;
+        } else if (typeAttrVal.EqualsLiteral("justify")) {
+          *aAlign = nsIHTMLEditor::eJustify;
+        } else {
+          *aAlign = nsIHTMLEditor::eLeft;
         }
+        return NS_OK;
       }
     }
     isFirstNodeToExamine = false;
-    nodeToExamine = nodeToExamine->GetParentNode();
   }
   return NS_OK;
 }
 
-static nsIAtom* MarginPropertyAtomForIndent(nsHTMLCSSUtils* aHTMLCSSUtils,
-                                            nsIDOMNode* aNode) {
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  NS_ENSURE_TRUE(node || !aNode, nsGkAtoms::marginLeft);
+static nsIAtom& MarginPropertyAtomForIndent(nsHTMLCSSUtils& aHTMLCSSUtils,
+                                            nsINode& aNode)
+{
   nsAutoString direction;
-  aHTMLCSSUtils->GetComputedProperty(*node, *nsGkAtoms::direction, direction);
+  aHTMLCSSUtils.GetComputedProperty(aNode, *nsGkAtoms::direction, direction);
   return direction.EqualsLiteral("rtl") ?
-    nsGkAtoms::marginRight : nsGkAtoms::marginLeft;
+    *nsGkAtoms::marginRight : *nsGkAtoms::marginLeft;
 }
 
 nsresult
 nsHTMLEditRules::GetIndentState(bool *aCanIndent, bool *aCanOutdent)
 {
   NS_ENSURE_TRUE(aCanIndent && aCanOutdent, NS_ERROR_FAILURE);
   *aCanIndent = true;
   *aCanOutdent = false;
@@ -979,24 +957,23 @@ nsHTMLEditRules::GetIndentState(bool *aC
   for (auto& curNode : Reversed(arrayOfNodes)) {
     if (nsHTMLEditUtils::IsNodeThatCanOutdent(GetAsDOMNode(curNode))) {
       *aCanOutdent = true;
       break;
     }
     else if (useCSS) {
       // we are in CSS mode, indentation is done using the margin-left (or margin-right) property
       NS_ENSURE_STATE(mHTMLEditor);
-      nsIAtom* marginProperty =
-        MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils,
-                                    GetAsDOMNode(curNode));
+      nsIAtom& marginProperty =
+        MarginPropertyAtomForIndent(*mHTMLEditor->mHTMLCSSUtils, curNode);
       nsAutoString value;
       // retrieve its specified value
       NS_ENSURE_STATE(mHTMLEditor);
       mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*curNode,
-                                                       *marginProperty, value);
+                                                       marginProperty, value);
       float f;
       nsCOMPtr<nsIAtom> unit;
       // get its number part and its unit
       NS_ENSURE_STATE(mHTMLEditor);
       mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit));
       // if the number part is strictly positive, outdent is possible
       if (0 < f) {
         *aCanOutdent = true;
@@ -1073,18 +1050,17 @@ nsHTMLEditRules::GetParagraphState(bool 
 
   // post process list.  We need to replace any block nodes that are not format
   // nodes with their content.  This is so we only have to look "up" the hierarchy
   // to find format nodes, instead of both up and down.
   for (int32_t i = arrayOfNodes.Length() - 1; i >= 0; i--) {
     auto& curNode = arrayOfNodes[i];
     nsAutoString format;
     // if it is a known format node we have it easy
-    if (IsBlockNode(GetAsDOMNode(curNode)) &&
-        !nsHTMLEditUtils::IsFormatNode(curNode)) {
+    if (IsBlockNode(curNode) && !nsHTMLEditUtils::IsFormatNode(curNode)) {
       // arrayOfNodes.RemoveObject(curNode);
       res = AppendInnerFormatNodes(arrayOfNodes, curNode);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
 
   // we might have an empty node list.  if so, find selection parent
   // and put that on the list
@@ -1107,17 +1083,17 @@ nsHTMLEditRules::GetParagraphState(bool 
   NS_ENSURE_TRUE(rootElem, NS_ERROR_NULL_POINTER);
 
   // loop through the nodes in selection and examine their paragraph format
   for (auto& curNode : Reversed(arrayOfNodes)) {
     nsAutoString format;
     // if it is a known format node we have it easy
     if (nsHTMLEditUtils::IsFormatNode(curNode)) {
       GetFormatString(GetAsDOMNode(curNode), format);
-    } else if (IsBlockNode(GetAsDOMNode(curNode))) {
+    } else if (IsBlockNode(curNode)) {
       // this is a div or some other non-format block.
       // we should ignore it.  Its children were appended to this list
       // by AppendInnerFormatNodes() call above.  We will get needed
       // info when we examine them instead.
       continue;
     }
     else
     {
@@ -1166,17 +1142,17 @@ nsHTMLEditRules::AppendInnerFormatNodes(
   // we only need to place any one inline inside this node onto
   // the list.  They are all the same for purposes of determining
   // paragraph style.  We use foundInline to track this as we are
   // going through the children in the loop below.
   bool foundInline = false;
   for (nsIContent* child = aNode->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
-    bool isBlock = IsBlockNode(child->AsDOMNode());
+    bool isBlock = IsBlockNode(*child);
     bool isFormat = nsHTMLEditUtils::IsFormatNode(child);
     if (isBlock && !isFormat) {
       // if it's a div, etc, recurse
       AppendInnerFormatNodes(aArray, child);
     } else if (isFormat) {
       aArray.AppendElement(*child);
     } else if (!foundInline) {
       // if this is the first inline we've found, use it
@@ -1301,21 +1277,20 @@ nsHTMLEditRules::WillInsertText(EditActi
   WillInsert(*aSelection, aCancel);
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
 
   // we need to get the doc
   NS_ENSURE_STATE(mHTMLEditor);
   nsCOMPtr<nsIDocument> doc = mHTMLEditor->GetDocument();
-  nsCOMPtr<nsIDOMDocument> domDoc = mHTMLEditor->GetDOMDocument();
-  NS_ENSURE_TRUE(doc && domDoc, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_STATE(doc);
 
   // for every property that is set, insert a new inline style node
-  res = CreateStyleForInsertText(aSelection, domDoc);
+  res = CreateStyleForInsertText(*aSelection, *doc);
   NS_ENSURE_SUCCESS(res, res);
 
   // get the (collapsed) selection location
   NS_ENSURE_STATE(mHTMLEditor);
   NS_ENSURE_STATE(aSelection->GetRangeAt(0));
   nsCOMPtr<nsINode> selNode = aSelection->GetRangeAt(0)->GetStartParent();
   int32_t selOffset = aSelection->GetRangeAt(0)->StartOffset();
   NS_ENSURE_STATE(selNode);
@@ -1574,33 +1549,31 @@ nsHTMLEditRules::WillInsertBreak(Selecti
     return NS_OK;
   }
 
   // If block is empty, populate with br.  (For example, imagine a div that
   // contains the word "text".  The user selects "text" and types return.
   // "Text" is deleted leaving an empty block.  We want to put in one br to
   // make block have a line.  Then code further below will put in a second br.)
   bool isEmpty;
-  IsEmptyBlock(GetAsDOMNode(blockParent), &isEmpty);
+  IsEmptyBlock(*blockParent, &isEmpty);
   if (isEmpty) {
     nsCOMPtr<Element> br = mHTMLEditor->CreateBR(blockParent,
                                                  blockParent->Length());
     NS_ENSURE_STATE(br);
   }
 
   nsCOMPtr<Element> listItem = IsInListItem(blockParent);
   if (listItem && listItem != host) {
-    ReturnInListItem(&aSelection, GetAsDOMNode(listItem), GetAsDOMNode(node),
-                     offset);
+    ReturnInListItem(aSelection, *listItem, node, offset);
     *aHandled = true;
     return NS_OK;
   } else if (nsHTMLEditUtils::IsHeader(*blockParent)) {
     // Headers: close (or split) header
-    ReturnInHeader(&aSelection, GetAsDOMNode(blockParent), GetAsDOMNode(node),
-                   offset);
+    ReturnInHeader(aSelection, *blockParent, node, offset);
     *aHandled = true;
     return NS_OK;
   } else if (blockParent->IsHTMLElement(nsGkAtoms::p)) {
     // Paragraphs: special rules to look for <br>s
     res = ReturnInParagraph(&aSelection, GetAsDOMNode(blockParent),
                             GetAsDOMNode(node), offset, aCancel, aHandled);
     NS_ENSURE_SUCCESS(res, res);
     // Fall through, we may not have handled it in ReturnInParagraph()
@@ -1694,17 +1667,17 @@ nsHTMLEditRules::StandardBreakImpl(nsINo
     // SetInterlinePosition(true) means we want the caret to stick to the
     // content on the "right".  We want the caret to stick to whatever is past
     // the break.  This is because the break is on the same line we were on,
     // but the next content will be on the following line.
 
     // An exception to this is if the break has a next sibling that is a block
     // node.  Then we stick to the left to avoid an uber caret.
     nsCOMPtr<nsIContent> siblingNode = brNode->GetNextSibling();
-    if (siblingNode && IsBlockNode(GetAsDOMNode(siblingNode))) {
+    if (siblingNode && IsBlockNode(*siblingNode)) {
       aSelection.SetInterlinePosition(false);
     } else {
       aSelection.SetInterlinePosition(true);
     }
     res = aSelection.Collapse(node, offset + 1);
     NS_ENSURE_SUCCESS(res, res);
   }
   return NS_OK;
@@ -1770,17 +1743,17 @@ nsHTMLEditRules::SplitMailCites(Selectio
     // want selection before the break, and on same line
     aSelection->SetInterlinePosition(true);
     res = aSelection->Collapse(selNode, newOffset);
     NS_ENSURE_SUCCESS(res, res);
     // if citeNode wasn't a block, we might also want another break before it.
     // We need to examine the content both before the br we just added and also
     // just after it.  If we don't have another br or block boundary adjacent,
     // then we will need a 2nd br added to achieve blank line that user expects.
-    if (IsInlineNode(GetAsDOMNode(citeNode))) {
+    if (IsInlineNode(*citeNode)) {
       NS_ENSURE_STATE(mHTMLEditor);
       nsWSRunObject wsObj(mHTMLEditor, selNode, newOffset);
       nsCOMPtr<nsINode> visNode;
       int32_t visOffset=0;
       WSType wsType;
       wsObj.PriorVisibleNode(selNode, newOffset, address_of(visNode),
                              &visOffset, &wsType);
       if (wsType == WSType::normalWS || wsType == WSType::text ||
@@ -2256,17 +2229,17 @@ nsHTMLEditRules::WillDeleteSelection(Sel
       }
       aSelection->Collapse(selPointNode, selPointOffset);
       return NS_OK;
     }
   }
 
 
   // Else we have a non-collapsed selection.  First adjust the selection.
-  res = ExpandSelectionForDeletion(aSelection);
+  res = ExpandSelectionForDeletion(*aSelection);
   NS_ENSURE_SUCCESS(res, res);
 
   // Remember that we did a ranged delete for the benefit of AfterEditInner().
   mDidRangedDelete = true;
 
   // Refresh start and end points
   NS_ENSURE_STATE(aSelection->GetRangeAt(0));
   startNode = aSelection->GetRangeAt(0)->GetStartParent();
@@ -2506,17 +2479,17 @@ nsHTMLEditRules::InsertBRIfNeeded(Select
   // get selection
   nsCOMPtr<nsINode> node;
   int32_t offset;
   nsresult res = mEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(node), &offset);
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
   // inline elements don't need any br
-  if (!IsBlockNode(GetAsDOMNode(node))) {
+  if (!IsBlockNode(*node)) {
     return NS_OK;
   }
 
   // examine selection
   NS_ENSURE_STATE(mHTMLEditor);
   nsWSRunObject wsObj(mHTMLEditor, node, offset);
   if (((wsObj.mStartReason & WSType::block) ||
        (wsObj.mStartReason & WSType::br)) &&
@@ -2672,31 +2645,28 @@ nsHTMLEditRules::JoinBlocks(nsIContent& 
       if (trackingRightBlock->IsElement()) {
         rightBlock = trackingRightBlock->AsElement();
       } else {
         NS_ENSURE_STATE(trackingRightBlock->GetParentElement());
         rightBlock = trackingRightBlock->GetParentElement();
       }
     }
     // Do br adjustment.
-    nsCOMPtr<nsIDOMNode> brNode;
-    res = CheckForInvisibleBR(GetAsDOMNode(leftBlock), kBlockEnd,
-                              address_of(brNode));
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<Element> brNode =
+      CheckForInvisibleBR(*leftBlock, BRLocation::blockEnd);
     if (mergeLists) {
       // The idea here is to take all children in rightList that are past
       // offset, and pull them into leftlist.
       for (nsCOMPtr<nsIContent> child = rightList->GetChildAt(offset);
            child; child = rightList->GetChildAt(rightOffset)) {
         res = mHTMLEditor->MoveNode(child, leftList, -1);
         NS_ENSURE_SUCCESS(res, res);
       }
     } else {
-      res = MoveBlock(GetAsDOMNode(leftBlock), GetAsDOMNode(rightBlock),
-                      leftOffset, rightOffset);
+      res = MoveBlock(*leftBlock, *rightBlock, leftOffset, rightOffset);
     }
     if (brNode) {
       mHTMLEditor->DeleteNode(brNode);
     }
   // Offset below is where you find yourself in leftBlock when you traverse
   // upwards from rightBlock
   } else if (nsEditorUtils::IsDescendantOf(rightBlock, leftBlock,
                                            &leftOffset)) {
@@ -2719,23 +2689,20 @@ nsHTMLEditRules::JoinBlocks(nsIContent& 
       if (trackingLeftBlock->IsElement()) {
         leftBlock = trackingLeftBlock->AsElement();
       } else {
         NS_ENSURE_STATE(trackingLeftBlock->GetParentElement());
         leftBlock = trackingLeftBlock->GetParentElement();
       }
     }
     // Do br adjustment.
-    nsCOMPtr<nsIDOMNode> brNode;
-    res = CheckForInvisibleBR(GetAsDOMNode(leftBlock), kBeforeBlock,
-                              address_of(brNode), leftOffset);
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<Element> brNode =
+      CheckForInvisibleBR(*leftBlock, BRLocation::beforeBlock, leftOffset);
     if (mergeLists) {
-      res = MoveContents(GetAsDOMNode(rightList), GetAsDOMNode(leftList),
-                         &leftOffset);
+      res = MoveContents(*rightList, *leftList, &leftOffset);
     } else {
       // Left block is a parent of right block, and the parent of the previous
       // visible content.  Right block is a child and contains the contents we
       // want to move.
 
       int32_t previousContentOffset;
       nsCOMPtr<nsINode> previousContentParent;
 
@@ -2764,182 +2731,164 @@ nsHTMLEditRules::JoinBlocks(nsIContent& 
         previousContentOffset++;
       }
 
       // 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 = mHTMLEditor->GetEditorRoot();
       if (!editorRoot || &aLeftNode != editorRoot) {
-        nsCOMPtr<nsIDOMNode> previousContentParentDOM =
-          GetAsDOMNode(previousContentParent);
-        nsCOMPtr<nsIDOMNode> splittedPreviousContentDOM;
-        res = mHTMLEditor->SplitStyleAbovePoint(address_of(previousContentParentDOM),
+        nsCOMPtr<nsIContent> splittedPreviousContent;
+        res = mHTMLEditor->SplitStyleAbovePoint(address_of(previousContentParent),
                                                 &previousContentOffset,
                                                 nullptr, nullptr, nullptr,
-                                                address_of(splittedPreviousContentDOM));
+                                                getter_AddRefs(splittedPreviousContent));
         NS_ENSURE_SUCCESS(res, res);
-        previousContentParent = do_QueryInterface(previousContentParentDOM);
-        NS_ENSURE_STATE(previousContentParent || !previousContentParentDOM);
-
-        if (splittedPreviousContentDOM) {
-          nsCOMPtr<nsINode> splittedPreviousContent =
-            do_QueryInterface(splittedPreviousContentDOM);
-          NS_ENSURE_STATE(splittedPreviousContent ||
-                          !splittedPreviousContentDOM);
+
+        if (splittedPreviousContent) {
           previousContentParent = splittedPreviousContent->GetParentNode();
           previousContentOffset = previousContentParent ?
             previousContentParent->IndexOf(splittedPreviousContent) : -1;
         }
       }
 
-      res = MoveBlock(GetAsDOMNode(previousContentParent),
-                      GetAsDOMNode(rightBlock),
-                      previousContentOffset, rightOffset);
+      NS_ENSURE_TRUE(previousContentParent, NS_ERROR_NULL_POINTER);
+
+      res = MoveBlock(*previousContentParent->AsElement(), *rightBlock,
+          previousContentOffset, rightOffset);
       NS_ENSURE_SUCCESS(res, res);
     }
     if (brNode) {
       mHTMLEditor->DeleteNode(brNode);
     }
   } else {
     // 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
     res = nsWSRunObject::PrepareToJoinBlocks(mHTMLEditor, leftBlock, rightBlock);
     NS_ENSURE_SUCCESS(res, res);
     // Do br adjustment.
-    nsCOMPtr<nsIDOMNode> brNode;
-    res = CheckForInvisibleBR(GetAsDOMNode(leftBlock), kBlockEnd,
-                              address_of(brNode));
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<Element> brNode =
+      CheckForInvisibleBR(*leftBlock, BRLocation::blockEnd);
     if (mergeLists || leftBlock->NodeInfo()->NameAtom() ==
                       rightBlock->NodeInfo()->NameAtom()) {
-      // Nodes are same type.  Merge them.
+      // Nodes are same type.  merge them.
       ::DOMPoint pt = JoinNodesSmart(*leftBlock, *rightBlock);
       if (pt.node && mergeLists) {
         nsCOMPtr<Element> newBlock;
         res = ConvertListType(rightBlock, getter_AddRefs(newBlock),
                               existingList, nsGkAtoms::li);
       }
     } else {
       // Nodes are dissimilar types.
-      res = MoveBlock(GetAsDOMNode(leftBlock), GetAsDOMNode(rightBlock),
-                      leftOffset, rightOffset);
+      res = MoveBlock(*leftBlock, *rightBlock, leftOffset, rightOffset);
       NS_ENSURE_SUCCESS(res, res);
     }
     if (brNode) {
       res = mHTMLEditor->DeleteNode(brNode);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return NS_OK;
 }
 
 
-/*****************************************************************************************************
-*    MoveBlock: this method is used to move the content from rightBlock into leftBlock
-*    Note that the "block" might merely be inline nodes between <br>s, or between blocks, etc.
-*    DTD containment rules are followed throughout.
-*         nsIDOMNode *aLeftBlock         parent to receive moved content
-*         nsIDOMNode *aRightBlock        parent to provide moved content
-*         int32_t aLeftOffset            offset in aLeftBlock to move content to
-*         int32_t aRightOffset           offset in aRightBlock to move content from
-*/
+/**
+ * Moves the content from aRightBlock starting from aRightOffset into
+ * aLeftBlock at aLeftOffset. Note that the "block" might merely be inline
+ * nodes between <br>s, or between blocks, etc.  DTD containment rules are
+ * followed throughout.
+ */
 nsresult
-nsHTMLEditRules::MoveBlock(nsIDOMNode *aLeftBlock, nsIDOMNode *aRightBlock, int32_t aLeftOffset, int32_t aRightOffset)
+nsHTMLEditRules::MoveBlock(Element& aLeftBlock, Element& aRightBlock,
+                           int32_t aLeftOffset, int32_t aRightOffset)
 {
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   // GetNodesFromPoint is the workhorse that figures out what we wnat to move.
-  nsresult res = GetNodesFromPoint(::DOMPoint(aRightBlock,aRightOffset),
+  nsresult res = GetNodesFromPoint(::DOMPoint(&aRightBlock, aRightOffset),
                                    EditAction::makeList, arrayOfNodes,
                                    TouchContent::yes);
   NS_ENSURE_SUCCESS(res, res);
-  for (auto& curNode : arrayOfNodes) {
+  for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
     // get the node to act on
-    if (IsBlockNode(GetAsDOMNode(curNode))) {
+    if (IsBlockNode(arrayOfNodes[i])) {
       // For block nodes, move their contents only, then delete block.
-      res = MoveContents(GetAsDOMNode(curNode), aLeftBlock, &aLeftOffset);
+      res = MoveContents(*arrayOfNodes[i]->AsElement(), aLeftBlock,
+                         &aLeftOffset);
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->DeleteNode(curNode);
-    }
-    else
-    {
-      // otherwise move the content as is, checking against the dtd.
-      res = MoveNodeSmart(GetAsDOMNode(curNode), aLeftBlock, &aLeftOffset);
-    }
-  }
-  return res;
-}
-
-/*****************************************************************************************************
-*    MoveNodeSmart: this method is used to move node aSource to (aDest,aOffset).
-*    DTD containment rules are followed throughout.  aOffset is updated to point _after_
-*    inserted content.
-*         nsIDOMNode *aSource       the selection.
-*         nsIDOMNode *aDest         parent to receive moved content
-*         int32_t *aOffset          offset in aDest to move content to
-*/
+      res = mHTMLEditor->DeleteNode(arrayOfNodes[i]);
+    } else {
+      // Otherwise move the content as is, checking against the DTD.
+      res = MoveNodeSmart(*arrayOfNodes[i]->AsContent(), aLeftBlock,
+                          &aLeftOffset);
+    }
+  }
+
+  // XXX We're only checking return value of the last iteration
+  NS_ENSURE_SUCCESS(res, res);
+  return NS_OK;
+}
+
+/**
+ * This method is used to move node aNode to (aDestElement, aInOutDestOffset).
+ * DTD containment rules are followed throughout.  aInOutDestOffset is updated
+ * to point _after_ inserted content.
+ */
 nsresult
-nsHTMLEditRules::MoveNodeSmart(nsIDOMNode *aSource, nsIDOMNode *aDest, int32_t *aOffset)
-{
-  nsCOMPtr<nsIContent> source = do_QueryInterface(aSource);
-  nsCOMPtr<nsINode> dest = do_QueryInterface(aDest);
-  NS_ENSURE_TRUE(source && dest && aOffset, NS_ERROR_NULL_POINTER);
-
-  nsresult res;
-  // check if this node can go into the destination node
+nsHTMLEditRules::MoveNodeSmart(nsIContent& aNode, Element& aDestElement,
+                               int32_t* aInOutDestOffset)
+{
+  MOZ_ASSERT(aInOutDestOffset);
+
   NS_ENSURE_STATE(mHTMLEditor);
-  if (mHTMLEditor->CanContain(*dest, *source)) {
-    // if it can, move it there
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->MoveNode(source, dest, *aOffset);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+  nsresult res;
+
+  // Check if this node can go into the destination node
+  if (mHTMLEditor->CanContain(aDestElement, aNode)) {
+    // If it can, move it there
+    res = mHTMLEditor->MoveNode(&aNode, &aDestElement, *aInOutDestOffset);
     NS_ENSURE_SUCCESS(res, res);
-    if (*aOffset != -1) ++(*aOffset);
-  }
-  else
-  {
-    // if it can't, move its children, and then delete it.
-    res = MoveContents(aSource, aDest, aOffset);
-    NS_ENSURE_SUCCESS(res, res);
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->DeleteNode(aSource);
+    if (*aInOutDestOffset != -1) {
+      (*aInOutDestOffset)++;
+    }
+  } else {
+    // If it can't, move its children (if any), and then delete it.
+    if (aNode.IsElement()) {
+      res = MoveContents(*aNode.AsElement(), aDestElement, aInOutDestOffset);
+      NS_ENSURE_SUCCESS(res, res);
+    }
+
+    res = mHTMLEditor->DeleteNode(&aNode);
     NS_ENSURE_SUCCESS(res, res);
   }
   return NS_OK;
 }
 
-/*****************************************************************************************************
-*    MoveContents: this method is used to move node the _contents_ of aSource to (aDest,aOffset).
-*    DTD containment rules are followed throughout.  aOffset is updated to point _after_
-*    inserted content.  aSource is deleted.
-*         nsIDOMNode *aSource       the selection.
-*         nsIDOMNode *aDest         parent to receive moved content
-*         int32_t *aOffset          offset in aDest to move content to
-*/
+/**
+ * Moves the _contents_ of aElement to (aDestElement, aInOutDestOffset).  DTD
+ * containment rules are followed throughout.  aInOutDestOffset is updated to
+ * point _after_ inserted content.
+ */
 nsresult
-nsHTMLEditRules::MoveContents(nsIDOMNode *aSource, nsIDOMNode *aDest, int32_t *aOffset)
-{
-  NS_ENSURE_TRUE(aSource && aDest && aOffset, NS_ERROR_NULL_POINTER);
-  if (aSource == aDest) return NS_ERROR_ILLEGAL_VALUE;
-  NS_ENSURE_STATE(mHTMLEditor);
-  NS_ASSERTION(!mHTMLEditor->IsTextNode(aSource), "#text does not have contents");
-
-  nsCOMPtr<nsIDOMNode> child;
-  nsAutoString tag;
-  nsresult res;
-  aSource->GetFirstChild(getter_AddRefs(child));
-  while (child)
-  {
-    res = MoveNodeSmart(child, aDest, aOffset);
+nsHTMLEditRules::MoveContents(Element& aElement, Element& aDestElement,
+                              int32_t* aInOutDestOffset)
+{
+  MOZ_ASSERT(aInOutDestOffset);
+
+  NS_ENSURE_TRUE(&aElement != &aDestElement, NS_ERROR_ILLEGAL_VALUE);
+
+  while (aElement.GetFirstChild()) {
+    nsresult res = MoveNodeSmart(*aElement.GetFirstChild(), aDestElement,
+                                 aInOutDestOffset);
     NS_ENSURE_SUCCESS(res, res);
-    aSource->GetFirstChild(getter_AddRefs(child));
   }
   return NS_OK;
 }
 
 
 nsresult
 nsHTMLEditRules::DeleteNonTableElements(nsINode* aNode)
 {
@@ -3047,17 +2996,17 @@ nsHTMLEditRules::WillMakeList(Selection*
                            aEntireList ? EntireList::yes : EntireList::no);
   NS_ENSURE_SUCCESS(res, res);
 
   // check if all our nodes are <br>s, or empty inlines
   bool bOnlyBreaks = true;
   for (auto& curNode : arrayOfNodes) {
     // if curNode is not a Break or empty inline, we're done
     if (!nsTextEditUtils::IsBreak(curNode) &&
-        !IsEmptyInline(GetAsDOMNode(curNode))) {
+        !IsEmptyInline(curNode)) {
       bOnlyBreaks = false;
       break;
     }
   }
 
   // if no nodes, we make empty list.  Ditto if the user tried to make a list
   // of some # of breaks.
   if (!arrayOfNodes.Length() || bOnlyBreaks) {
@@ -3090,17 +3039,17 @@ nsHTMLEditRules::WillMakeList(Selection*
     NS_ENSURE_STATE(theList);
 
     NS_ENSURE_STATE(mHTMLEditor);
     nsCOMPtr<Element> theListItem =
       mHTMLEditor->CreateNode(itemType, theList, 0);
     NS_ENSURE_STATE(theListItem);
 
     // remember our new block for postprocessing
-    mNewBlock = GetAsDOMNode(theListItem);
+    mNewBlock = theListItem;
     // put selection in new list item
     res = aSelection->Collapse(theListItem, 0);
     // to prevent selection resetter from overriding us
     selectionResetter.Abort();
     *aHandled = true;
     return res;
   }
 
@@ -3113,36 +3062,36 @@ nsHTMLEditRules::WillMakeList(Selection*
   // or whatever is approriate.  Wohoo!
 
   uint32_t listCount = arrayOfNodes.Length();
   nsCOMPtr<nsINode> curParent;
   nsCOMPtr<Element> curList, prevListItem;
 
   for (uint32_t i = 0; i < listCount; i++) {
     // here's where we actually figure out what to do
-    nsCOMPtr<nsIDOMNode> newBlock;
+    nsCOMPtr<Element> newBlock;
     NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
-    nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent();
+    OwningNonNull<nsIContent> curNode = *arrayOfNodes[i]->AsContent();
     int32_t offset;
     curParent = nsEditor::GetNodeLocation(curNode, &offset);
 
     // make sure we don't assemble content that is in different table cells
     // 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 (nsTextEditUtils::IsBreak(curNode)) {
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       prevListItem = 0;
       continue;
-    } else if (IsEmptyInline(GetAsDOMNode(curNode))) {
+    } else if (IsEmptyInline(curNode)) {
       // if curNode is an empty inline container, delete it
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       continue;
     }
 
     if (nsHTMLEditUtils::IsList(curNode)) {
@@ -3150,80 +3099,81 @@ nsHTMLEditRules::WillMakeList(Selection*
       if (curList && !nsEditorUtils::IsDescendantOf(curNode, curList)) {
         // move all of our children into curList.  cheezy way to do it: move
         // whole list and then RemoveContainer() on the list.  ConvertListType
         // first: that routine handles converting the list item types, if
         // needed
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->MoveNode(curNode, curList, -1);
         NS_ENSURE_SUCCESS(res, res);
-        res = ConvertListType(GetAsDOMNode(curNode), address_of(newBlock),
+        res = ConvertListType(curNode->AsElement(), getter_AddRefs(newBlock),
                               listType, itemType);
         NS_ENSURE_SUCCESS(res, res);
         NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->RemoveBlockContainer(newBlock);
+        res = mHTMLEditor->RemoveBlockContainer(*newBlock);
         NS_ENSURE_SUCCESS(res, res);
       } else {
         // replace list with new list type
-        res = ConvertListType(GetAsDOMNode(curNode), address_of(newBlock),
+        res = ConvertListType(curNode->AsElement(), getter_AddRefs(newBlock),
                               listType, itemType);
         NS_ENSURE_SUCCESS(res, res);
-        curList = do_QueryInterface(newBlock);
+        curList = newBlock;
       }
       prevListItem = 0;
       continue;
     }
 
     if (nsHTMLEditUtils::IsListItem(curNode)) {
       NS_ENSURE_STATE(mHTMLEditor);
       if (!curParent->IsHTMLElement(listType)) {
         // 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 || nsEditorUtils::IsDescendantOf(curNode, curList)) {
           NS_ENSURE_STATE(mHTMLEditor);
-          res = mHTMLEditor->SplitNode(curParent->AsDOMNode(), offset,
-                                       getter_AddRefs(newBlock));
-          NS_ENSURE_SUCCESS(res, res);
+          NS_ENSURE_STATE(curParent->IsContent());
+          ErrorResult rv;
+          nsCOMPtr<nsIContent> splitNode =
+            mHTMLEditor->SplitNode(*curParent->AsContent(), offset, rv);
+          NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
+          newBlock = splitNode ? splitNode->AsElement() : nullptr;
           int32_t offset;
           nsCOMPtr<nsINode> parent = nsEditor::GetNodeLocation(curParent,
                                                                &offset);
           NS_ENSURE_STATE(mHTMLEditor);
           curList = mHTMLEditor->CreateNode(listType, parent, offset);
           NS_ENSURE_STATE(curList);
         }
         // move list item to new list
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->MoveNode(curNode, curList, -1);
         NS_ENSURE_SUCCESS(res, res);
         // convert list item type if needed
         NS_ENSURE_STATE(mHTMLEditor);
         if (!curNode->IsHTMLElement(itemType)) {
           NS_ENSURE_STATE(mHTMLEditor);
-          newBlock = dont_AddRef(GetAsDOMNode(
-            mHTMLEditor->ReplaceContainer(curNode->AsElement(),
-                                          itemType).take()));
+          newBlock = mHTMLEditor->ReplaceContainer(curNode->AsElement(),
+                                                   itemType);
           NS_ENSURE_STATE(newBlock);
         }
       } 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 = curParent->AsElement();
         } else if (curParent != curList) {
           // move list item to new list
           NS_ENSURE_STATE(mHTMLEditor);
           res = mHTMLEditor->MoveNode(curNode, curList, -1);
           NS_ENSURE_SUCCESS(res, res);
         }
         NS_ENSURE_STATE(mHTMLEditor);
         if (!curNode->IsHTMLElement(itemType)) {
           NS_ENSURE_STATE(mHTMLEditor);
-          newBlock = dont_AddRef(GetAsDOMNode(
-            mHTMLEditor->ReplaceContainer(curNode->AsElement(),
-                                          itemType).take()));
+          newBlock = mHTMLEditor->ReplaceContainer(curNode->AsElement(),
+                                                   itemType);
           NS_ENSURE_STATE(newBlock);
         }
       }
       nsCOMPtr<nsIDOMElement> curElement = do_QueryInterface(curNode);
       NS_NAMED_LITERAL_STRING(typestr, "type");
       if (aBulletType && !aBulletType->IsEmpty()) {
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->SetAttribute(curElement, typestr, *aBulletType);
@@ -3251,25 +3201,25 @@ nsHTMLEditRules::WillMakeList(Selection*
     // need to make a list to put things in if we haven't already,
     if (!curList) {
       res = SplitAsNeeded(listType, curParent, offset);
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_STATE(mHTMLEditor);
       curList = mHTMLEditor->CreateNode(listType, curParent, offset);
       NS_ENSURE_SUCCESS(res, res);
       // remember our new block for postprocessing
-      mNewBlock = GetAsDOMNode(curList);
+      mNewBlock = curList;
       // curList is now the correct thing to put curNode in
       prevListItem = 0;
     }
 
     // if curNode isn't a list item, we must wrap it in one
     nsCOMPtr<Element> listItem;
     if (!nsHTMLEditUtils::IsListItem(curNode)) {
-      if (IsInlineNode(GetAsDOMNode(curNode)) && prevListItem) {
+      if (IsInlineNode(curNode) && prevListItem) {
         // this is a continuation of some inline nodes that belong together in
         // the same list item.  use prevListItem
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->MoveNode(curNode, prevListItem, -1);
         NS_ENSURE_SUCCESS(res, res);
       } else {
         // don't wrap li around a paragraph.  instead replace paragraph with li
         if (curNode->IsHTMLElement(nsGkAtoms::p)) {
@@ -3277,17 +3227,17 @@ nsHTMLEditRules::WillMakeList(Selection*
           listItem = mHTMLEditor->ReplaceContainer(curNode->AsElement(),
                                                    itemType);
           NS_ENSURE_STATE(listItem);
         } else {
           NS_ENSURE_STATE(mHTMLEditor);
           listItem = mHTMLEditor->InsertContainerAbove(curNode, itemType);
           NS_ENSURE_STATE(listItem);
         }
-        if (IsInlineNode(GetAsDOMNode(curNode))) {
+        if (IsInlineNode(curNode)) {
           prevListItem = listItem;
         } else {
           prevListItem = nullptr;
         }
       }
     } else {
       listItem = curNode->AsElement();
     }
@@ -3354,17 +3304,17 @@ nsHTMLEditRules::WillRemoveList(Selectio
       do
       {
         res = PopListItem(GetAsDOMNode(curNode), &bOutOfList);
         NS_ENSURE_SUCCESS(res, res);
       } while (!bOutOfList); // keep popping it out until it's not in a list anymore
     }
     else if (nsHTMLEditUtils::IsList(curNode)) // node is a list, move list items out
     {
-      res = RemoveListStructure(GetAsDOMNode(curNode));
+      res = RemoveListStructure(*curNode->AsElement());
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return res;
 }
 
 
 nsresult
@@ -3375,182 +3325,159 @@ nsHTMLEditRules::WillMakeDefListItem(Sel
                                      bool *aHandled)
 {
   // for now we let WillMakeList handle this
   NS_NAMED_LITERAL_STRING(listType, "dl");
   return WillMakeList(aSelection, &listType, aEntireList, nullptr, aCancel, aHandled, aItemType);
 }
 
 nsresult
-nsHTMLEditRules::WillMakeBasicBlock(Selection* aSelection,
-                                    const nsAString *aBlockType,
-                                    bool *aCancel,
-                                    bool *aHandled)
-{
-  OwningNonNull<nsIAtom> blockType = NS_Atomize(*aBlockType);
-  if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
-  // initialize out param
+nsHTMLEditRules::WillMakeBasicBlock(Selection& aSelection,
+                                    const nsAString& aBlockType,
+                                    bool* aCancel,
+                                    bool* aHandled)
+{
+  MOZ_ASSERT(aCancel && aHandled);
+
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  OwningNonNull<nsIAtom> blockType = NS_Atomize(aBlockType);
+
+  WillInsert(aSelection, aCancel);
+  // We want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = false;
 
-  WillInsert(*aSelection, aCancel);
-  // initialize out param
-  // we want to ignore result of WillInsert()
-  *aCancel = false;
-  nsresult res = NormalizeSelection(aSelection);
+  nsresult res = NormalizeSelection(&aSelection);
   NS_ENSURE_SUCCESS(res, res);
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
-  NS_ENSURE_STATE(mHTMLEditor);
+  nsAutoSelectionReset selectionResetter(&aSelection, mHTMLEditor);
   nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
   *aHandled = true;
-  nsString tString(*aBlockType);
-
-  // contruct a list of nodes to act on.
+
+  // Contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
-  res = GetNodesFromSelection(*aSelection, EditAction::makeBasicBlock,
+  res = GetNodesFromSelection(aSelection, EditAction::makeBasicBlock,
                               arrayOfNodes);
   NS_ENSURE_SUCCESS(res, res);
 
   // Remove all non-editable nodes.  Leave them be.
-  int32_t listCount = arrayOfNodes.Length();
-  int32_t i;
-  for (i=listCount-1; i>=0; i--)
-  {
-    NS_ENSURE_STATE(mHTMLEditor);
+  for (int32_t i = arrayOfNodes.Length() - 1; i >= 0; i--) {
     if (!mHTMLEditor->IsEditable(arrayOfNodes[i])) {
       arrayOfNodes.RemoveElementAt(i);
     }
   }
 
-  // reset list count
-  listCount = arrayOfNodes.Length();
-
-  // if nothing visible in list, make an empty block
-  if (ListIsEmptyLine(arrayOfNodes))
-  {
-    nsCOMPtr<nsIDOMNode> theBlock;
-
-    // get selection location
-    NS_ENSURE_STATE(aSelection->RangeCount());
-    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
-    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
-    NS_ENSURE_STATE(parent);
-    if (tString.EqualsLiteral("normal") ||
-        tString.IsEmpty() ) // we are removing blocks (going to "body text")
-    {
-      NS_ENSURE_STATE(mHTMLEditor);
-      nsCOMPtr<Element> curBlock = mHTMLEditor->GetBlock(*parent);
-      NS_ENSURE_TRUE(curBlock, NS_ERROR_NULL_POINTER);
-      nsCOMPtr<nsIDOMNode> curBlockPar =
-        GetAsDOMNode(curBlock->GetParentNode());
-      if (nsHTMLEditUtils::IsFormatNode(curBlock))
-      {
-        // 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<nsIDOMNode> brNode;
-        NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->GetNextHTMLNode(parent->AsDOMNode(), offset,
-                                           address_of(brNode));
-        NS_ENSURE_SUCCESS(res, res);
-        if (brNode && nsTextEditUtils::IsBreak(brNode))
-        {
-          NS_ENSURE_STATE(mHTMLEditor);
+  // If nothing visible in list, make an empty block
+  if (ListIsEmptyLine(arrayOfNodes)) {
+    // Get selection location
+    NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
+                    aSelection.GetRangeAt(0)->GetStartParent());
+    OwningNonNull<nsINode> parent =
+      *aSelection.GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
+
+    if (blockType == nsGkAtoms::normal ||
+        blockType == nsGkAtoms::_empty) {
+      // We are removing blocks (going to "body text")
+      NS_ENSURE_TRUE(mHTMLEditor->GetBlock(parent), NS_ERROR_NULL_POINTER);
+      OwningNonNull<Element> curBlock = *mHTMLEditor->GetBlock(parent);
+      if (nsHTMLEditUtils::IsFormatNode(curBlock)) {
+        // 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> brNode =
+          mHTMLEditor->GetNextHTMLNode(parent, offset);
+        if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
           res = mHTMLEditor->DeleteNode(brNode);
           NS_ENSURE_SUCCESS(res, res);
         }
-        // do the splits!
-        NS_ENSURE_STATE(mHTMLEditor);
-        offset = mHTMLEditor->SplitNodeDeep(*curBlock, *parent->AsContent(),
+        // Do the splits!
+        offset = mHTMLEditor->SplitNodeDeep(curBlock, *parent->AsContent(),
                                             offset,
                                             nsHTMLEditor::EmptyContainers::no);
         NS_ENSURE_STATE(offset != -1);
-        // put a br at the split point
-        NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->CreateBR(curBlockPar, offset, address_of(brNode));
-        NS_ENSURE_SUCCESS(res, res);
-        // put selection at the split point
-        res = aSelection->Collapse(curBlockPar, offset);
-        selectionResetter.Abort();  // to prevent selection reseter from overriding us.
+        // Put a br at the split point
+        brNode = mHTMLEditor->CreateBR(curBlock->GetParentNode(), offset);
+        NS_ENSURE_STATE(brNode);
+        // Put selection at the split point
+        res = aSelection.Collapse(curBlock->GetParentNode(), offset);
+        // To prevent selection resetter from overriding us.
+        selectionResetter.Abort();
         *aHandled = true;
-      }
-      // else nothing to do!
-    }
-    else  // we are making a block
-    {
-      // consume a br, if needed
-      NS_ENSURE_STATE(mHTMLEditor);
+        NS_ENSURE_SUCCESS(res, res);
+      }
+      // Else nothing to do!
+    } else {
+      // We are making a block.  Consume a br, if needed.
       nsCOMPtr<nsIContent> brNode =
         mHTMLEditor->GetNextHTMLNode(parent, offset, true);
-      NS_ENSURE_SUCCESS(res, res);
-      if (brNode && nsTextEditUtils::IsBreak(brNode))
-      {
-        NS_ENSURE_STATE(mHTMLEditor);
+      if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
         res = mHTMLEditor->DeleteNode(brNode);
         NS_ENSURE_SUCCESS(res, res);
-        // we don't need to act on this node any more
+        // We don't need to act on this node any more
         arrayOfNodes.RemoveElement(brNode);
       }
-      // make sure we can put a block here
+      // Make sure we can put a block here
       res = SplitAsNeeded(blockType, parent, offset);
       NS_ENSURE_SUCCESS(res, res);
-      NS_ENSURE_STATE(mHTMLEditor);
-      theBlock = dont_AddRef(GetAsDOMNode(
-        mHTMLEditor->CreateNode(blockType, parent, offset).take()));
-      NS_ENSURE_STATE(theBlock);
-      // remember our new block for postprocessing
-      mNewBlock = theBlock;
-      // delete anything that was in the list of nodes
+      nsCOMPtr<Element> block =
+        mHTMLEditor->CreateNode(blockType, parent, offset);
+      NS_ENSURE_STATE(block);
+      // 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];
-        NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->DeleteNode(curNode);
         NS_ENSURE_SUCCESS(res, res);
         arrayOfNodes.RemoveElementAt(0);
       }
-      // put selection in new block
-      res = aSelection->Collapse(theBlock,0);
-      selectionResetter.Abort();  // to prevent selection reseter from overriding us.
+      // Put selection in new block
+      res = aSelection.Collapse(block, 0);
+      // To prevent selection resetter from overriding us.
+      selectionResetter.Abort();
       *aHandled = true;
-    }
-    return res;
-  }
-  else
-  {
-    // Ok, now go through all the nodes and make the right kind of blocks,
-    // or whatever is approriate.  Wohoo!
-    // Note: blockquote is handled a little differently
-    if (tString.EqualsLiteral("blockquote")) {
-      res = MakeBlockquote(arrayOfNodes);
-    } else if (tString.EqualsLiteral("normal") || tString.IsEmpty()) {
-      res = RemoveBlockStyle(arrayOfNodes);
-    } else {
-      res = ApplyBlockStyle(arrayOfNodes, *blockType);
-    }
-    return res;
-  }
-  return res;
+      NS_ENSURE_SUCCESS(res, res);
+    }
+    return NS_OK;
+  }
+  // Okay, now go through all the nodes and make the right kind of blocks, or
+  // whatever is approriate.  Woohoo!  Note: blockquote is handled a little
+  // differently.
+  if (blockType == nsGkAtoms::blockquote) {
+    res = MakeBlockquote(arrayOfNodes);
+    NS_ENSURE_SUCCESS(res, res);
+  } else if (blockType == nsGkAtoms::normal ||
+             blockType == nsGkAtoms::_empty) {
+    res = RemoveBlockStyle(arrayOfNodes);
+    NS_ENSURE_SUCCESS(res, res);
+  } else {
+    res = ApplyBlockStyle(arrayOfNodes, blockType);
+    NS_ENSURE_SUCCESS(res, res);
+  }
+  return NS_OK;
 }
 
 nsresult
 nsHTMLEditRules::DidMakeBasicBlock(Selection* aSelection,
                                    nsRulesInfo *aInfo, nsresult aResult)
 {
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
   // check for empty block.  if so, put a moz br in it.
   if (!aSelection->Collapsed()) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMNode> parent;
-  int32_t offset;
-  nsresult res = nsEditor::GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
+  NS_ENSURE_STATE(aSelection->GetRangeAt(0) &&
+                  aSelection->GetRangeAt(0)->GetStartParent());
+  nsresult res =
+    InsertMozBRIfNeeded(*aSelection->GetRangeAt(0)->GetStartParent());
   NS_ENSURE_SUCCESS(res, res);
-  res = InsertMozBRIfNeeded(parent);
-  return res;
+  return NS_OK;
 }
 
 nsresult
 nsHTMLEditRules::WillIndent(Selection* aSelection,
                             bool* aCancel, bool* aHandled)
 {
   nsresult res;
   NS_ENSURE_STATE(mHTMLEditor);
@@ -3624,18 +3551,18 @@ nsHTMLEditRules::WillCSSIndent(Selection
     // make sure we can put a block here
     res = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_STATE(mHTMLEditor);
     nsCOMPtr<Element> theBlock = mHTMLEditor->CreateNode(nsGkAtoms::div,
                                                          parent, offset);
     NS_ENSURE_STATE(theBlock);
     // remember our new block for postprocessing
-    mNewBlock = theBlock->AsDOMNode();
-    RelativeChangeIndentationOfElementNode(theBlock->AsDOMNode(), +1);
+    mNewBlock = theBlock;
+    ChangeIndentation(*theBlock, Change::plus);
     // delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       arrayOfNodes.RemoveElementAt(0);
     }
@@ -3716,48 +3643,48 @@ nsHTMLEditRules::WillCSSIndent(Selection
                             offset);
         NS_ENSURE_SUCCESS(res, res);
         NS_ENSURE_STATE(mHTMLEditor);
         curList = mHTMLEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
                                           curParent, offset);
         NS_ENSURE_STATE(curList);
         // curList is now the correct thing to put curNode in
         // remember our new block for postprocessing
-        mNewBlock = curList->AsDOMNode();
+        mNewBlock = curList;
       }
       // tuck the node into the end of the active list
       uint32_t listLen = curList->Length();
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->MoveNode(curNode, curList, listLen);
       NS_ENSURE_SUCCESS(res, res);
     }
 
     else // not a list item
     {
-      if (IsBlockNode(curNode->AsDOMNode())) {
-        RelativeChangeIndentationOfElementNode(curNode->AsDOMNode(), +1);
+      if (curNode && IsBlockNode(*curNode)) {
+        ChangeIndentation(*curNode->AsElement(), Change::plus);
         curQuote = nullptr;
       }
       else {
         if (!curQuote)
         {
           // First, check that our element can contain a div.
           if (!mEditor->CanContainTag(*curParent, *nsGkAtoms::div)) {
             return NS_OK; // cancelled
           }
 
           res = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
           NS_ENSURE_SUCCESS(res, res);
           NS_ENSURE_STATE(mHTMLEditor);
           curQuote = mHTMLEditor->CreateNode(nsGkAtoms::div, curParent,
                                              offset);
           NS_ENSURE_STATE(curQuote);
-          RelativeChangeIndentationOfElementNode(curQuote->AsDOMNode(), +1);
+          ChangeIndentation(*curQuote, Change::plus);
           // remember our new block for postprocessing
-          mNewBlock = curQuote->AsDOMNode();
+          mNewBlock = curQuote;
           // curQuote is now the correct thing to put curNode in
         }
 
         // tuck the node into the end of the active blockquote
         uint32_t quoteLen = curQuote->Length();
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->MoveNode(curNode, curQuote, quoteLen);
         NS_ENSURE_SUCCESS(res, res);
@@ -3809,17 +3736,17 @@ nsHTMLEditRules::WillHTMLIndent(Selectio
     // make sure we can put a block here
     res = SplitAsNeeded(*nsGkAtoms::blockquote, parent, offset);
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_STATE(mHTMLEditor);
     nsCOMPtr<Element> theBlock = mHTMLEditor->CreateNode(nsGkAtoms::blockquote,
                                                          parent, offset);
     NS_ENSURE_STATE(theBlock);
     // remember our new block for postprocessing
-    mNewBlock = theBlock->AsDOMNode();
+    mNewBlock = theBlock;
     // delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       arrayOfNodes.RemoveElementAt(0);
     }
@@ -3899,17 +3826,17 @@ nsHTMLEditRules::WillHTMLIndent(Selectio
                             offset);
         NS_ENSURE_SUCCESS(res, res);
         NS_ENSURE_STATE(mHTMLEditor);
         curList = mHTMLEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
                                           curParent, offset);
         NS_ENSURE_STATE(curList);
         // curList is now the correct thing to put curNode in
         // remember our new block for postprocessing
-        mNewBlock = curList->AsDOMNode();
+        mNewBlock = curList;
       }
       // tuck the node into the end of the active list
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->MoveNode(curNode, curList, -1);
       NS_ENSURE_SUCCESS(res, res);
       // forget curQuote, if any
       curQuote = nullptr;
     }
@@ -3976,17 +3903,17 @@ nsHTMLEditRules::WillHTMLIndent(Selectio
 
           res = SplitAsNeeded(*nsGkAtoms::blockquote, curParent, offset);
           NS_ENSURE_SUCCESS(res, res);
           NS_ENSURE_STATE(mHTMLEditor);
           curQuote = mHTMLEditor->CreateNode(nsGkAtoms::blockquote, curParent,
                                              offset);
           NS_ENSURE_STATE(curQuote);
           // remember our new block for postprocessing
-          mNewBlock = curQuote->AsDOMNode();
+          mNewBlock = curQuote;
           // curQuote is now the correct thing to put curNode in
         }
 
         // tuck the node into the end of the active blockquote
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->MoveNode(curNode, curQuote, -1);
         NS_ENSURE_SUCCESS(res, res);
         // forget curList, if any
@@ -3994,421 +3921,372 @@ nsHTMLEditRules::WillHTMLIndent(Selectio
       }
     }
   }
   return res;
 }
 
 
 nsresult
-nsHTMLEditRules::WillOutdent(Selection* aSelection,
+nsHTMLEditRules::WillOutdent(Selection& aSelection,
                              bool* aCancel, bool* aHandled)
 {
-  if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
-  // initialize out param
+  MOZ_ASSERT(aCancel && aHandled);
   *aCancel = false;
   *aHandled = true;
-  nsresult res = NS_OK;
-  nsCOMPtr<nsIDOMNode> rememberedLeftBQ, rememberedRightBQ;
+  nsCOMPtr<nsIContent> rememberedLeftBQ, rememberedRightBQ;
   NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
   bool useCSS = mHTMLEditor->IsCSSEnabled();
 
-  res = NormalizeSelection(aSelection);
+  nsresult res = NormalizeSelection(&aSelection);
   NS_ENSURE_SUCCESS(res, res);
-  // some scoping for selection resetting - we may need to tweak it
+
+  // Some scoping for selection resetting - we may need to tweak it
   {
-    NS_ENSURE_STATE(mHTMLEditor);
-    nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
-
-    // 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
+    nsAutoSelectionReset selectionResetter(&aSelection, mHTMLEditor);
+
+    // 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;
-    res = GetNodesFromSelection(*aSelection, EditAction::outdent,
+    res = GetNodesFromSelection(aSelection, EditAction::outdent,
                                 arrayOfNodes);
     NS_ENSURE_SUCCESS(res, res);
 
-    // Ok, now go through all the nodes and remove a level of blockquoting,
+    // Okay, now go through all the nodes and remove a level of blockquoting,
     // or whatever is appropriate.  Wohoo!
 
-    nsCOMPtr<nsIDOMNode> curBlockQuote, firstBQChild, lastBQChild;
+    nsCOMPtr<Element> curBlockQuote;
+    nsCOMPtr<nsIContent> firstBQChild, lastBQChild;
     bool curBlockQuoteIsIndentedWithCSS = false;
-    for (auto& curNode : arrayOfNodes) {
-      // here's where we actually figure out what to do
+    for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
+      if (!arrayOfNodes[i]->IsContent()) {
+        continue;
+      }
+      OwningNonNull<nsIContent> curNode = *arrayOfNodes[i]->AsContent();
+
+      // Here's where we actually figure out what to do
       nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
       int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
 
-      // is it a blockquote?
+      // Is it a blockquote?
       if (curNode->IsHTMLElement(nsGkAtoms::blockquote)) {
-        // if it is a blockquote, remove it.
-        // So we need to finish up dealng with any curBlockQuote first.
-        if (curBlockQuote)
-        {
-          res = OutdentPartOfBlock(curBlockQuote, firstBQChild, lastBQChild,
+        // If it is a blockquote, remove it.  So we need to finish up dealng
+        // with any curBlockQuote first.
+        if (curBlockQuote) {
+          res = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
                                    curBlockQuoteIsIndentedWithCSS,
-                                   address_of(rememberedLeftBQ),
-                                   address_of(rememberedRightBQ));
+                                   getter_AddRefs(rememberedLeftBQ),
+                                   getter_AddRefs(rememberedRightBQ));
           NS_ENSURE_SUCCESS(res, res);
-          curBlockQuote = 0;  firstBQChild = 0;  lastBQChild = 0;
+          curBlockQuote = nullptr;
+          firstBQChild = nullptr;
+          lastBQChild = nullptr;
           curBlockQuoteIsIndentedWithCSS = false;
         }
-        NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->RemoveBlockContainer(GetAsDOMNode(curNode));
+        res = mHTMLEditor->RemoveBlockContainer(curNode);
         NS_ENSURE_SUCCESS(res, res);
         continue;
       }
-      // is it a block with a 'margin' property?
-      if (useCSS && IsBlockNode(GetAsDOMNode(curNode))) {
-        NS_ENSURE_STATE(mHTMLEditor);
-        nsIAtom* marginProperty =
-          MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils,
-                                      GetAsDOMNode(curNode));
+      // Is it a block with a 'margin' property?
+      if (useCSS && IsBlockNode(curNode)) {
+        nsIAtom& marginProperty =
+          MarginPropertyAtomForIndent(*mHTMLEditor->mHTMLCSSUtils, curNode);
         nsAutoString value;
-        NS_ENSURE_STATE(mHTMLEditor);
-        mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*curNode,
-                                                         *marginProperty,
+        mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(curNode,
+                                                         marginProperty,
                                                          value);
         float f;
         nsCOMPtr<nsIAtom> unit;
         NS_ENSURE_STATE(mHTMLEditor);
         mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit));
-        if (f > 0)
-        {
-          RelativeChangeIndentationOfElementNode(GetAsDOMNode(curNode), -1);
+        if (f > 0) {
+          ChangeIndentation(*curNode->AsElement(), Change::minus);
           continue;
         }
       }
-      // is it a list item?
-      if (nsHTMLEditUtils::IsListItem(curNode))
-      {
-        // if it is a list item, that means we are not outdenting whole list.
-        // So we need to finish up dealing with any curBlockQuote, and then
-        // pop this list item.
-        if (curBlockQuote)
-        {
-          res = OutdentPartOfBlock(curBlockQuote, firstBQChild, lastBQChild,
+      // Is it a list item?
+      if (nsHTMLEditUtils::IsListItem(curNode)) {
+        // If it is a list item, that means we are not outdenting whole list.
+        // So we need to finish up dealing with any curBlockQuote, and then pop
+        // this list item.
+        if (curBlockQuote) {
+          res = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
                                    curBlockQuoteIsIndentedWithCSS,
-                                   address_of(rememberedLeftBQ),
-                                   address_of(rememberedRightBQ));
+                                   getter_AddRefs(rememberedLeftBQ),
+                                   getter_AddRefs(rememberedRightBQ));
           NS_ENSURE_SUCCESS(res, res);
-          curBlockQuote = 0;  firstBQChild = 0;  lastBQChild = 0;
+          curBlockQuote = nullptr;
+          firstBQChild = nullptr;
+          lastBQChild = nullptr;
           curBlockQuoteIsIndentedWithCSS = false;
         }
-        bool bOutOfList;
-        res = PopListItem(GetAsDOMNode(curNode), &bOutOfList);
+        bool unused;
+        res = PopListItem(GetAsDOMNode(curNode), &unused);
         NS_ENSURE_SUCCESS(res, res);
         continue;
       }
-      // do we have a blockquote that we are already committed to removing?
-      if (curBlockQuote)
-      {
-        // if so, is this node a descendant?
-        if (nsEditorUtils::IsDescendantOf(GetAsDOMNode(curNode),
-                                          curBlockQuote)) {
-          lastBQChild = GetAsDOMNode(curNode);
-          continue;  // then we don't need to do anything different for this node
-        }
-        else
-        {
-          // otherwise, we have progressed beyond end of curBlockQuote,
-          // so lets handle it now.  We need to remove the portion of
+      // Do we have a blockquote that we are already committed to removing?
+      if (curBlockQuote) {
+        // If so, is this node a descendant?
+        if (nsEditorUtils::IsDescendantOf(curNode, curBlockQuote)) {
+          lastBQChild = curNode;
+          // Then we don't need to do anything different for this node
+          continue;
+        } else {
+          // Otherwise, we have progressed beyond end of curBlockQuote, so
+          // let's handle it now.  We need to remove the portion of
           // curBlockQuote that contains [firstBQChild - lastBQChild].
-          res = OutdentPartOfBlock(curBlockQuote, firstBQChild, lastBQChild,
+          res = OutdentPartOfBlock(*curBlockQuote, *firstBQChild,
+                                   *lastBQChild,
                                    curBlockQuoteIsIndentedWithCSS,
-                                   address_of(rememberedLeftBQ),
-                                   address_of(rememberedRightBQ));
+                                   getter_AddRefs(rememberedLeftBQ),
+                                   getter_AddRefs(rememberedRightBQ));
           NS_ENSURE_SUCCESS(res, res);
-          curBlockQuote = 0;  firstBQChild = 0;  lastBQChild = 0;
+          curBlockQuote = nullptr;
+          firstBQChild = nullptr;
+          lastBQChild = nullptr;
           curBlockQuoteIsIndentedWithCSS = false;
-          // fall out and handle curNode
+          // Fall out and handle curNode
         }
       }
 
-      // are we inside a blockquote?
-      nsCOMPtr<nsINode> n = curNode;
+      // 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
+      // 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) && mHTMLEditor &&
+      while (!n->IsHTMLElement(nsGkAtoms::body) && 
              mHTMLEditor->IsDescendantOfEditorRoot(n) &&
              (n->IsHTMLElement(nsGkAtoms::table) ||
               !nsHTMLEditUtils::IsTableElement(n))) {
         if (!n->GetParentNode()) {
           break;
         }
-        n = n->GetParentNode();
+        n = *n->GetParentNode();
         if (n->IsHTMLElement(nsGkAtoms::blockquote)) {
-          // if so, remember it, and remember first node we are taking out of it.
-          curBlockQuote = GetAsDOMNode(n);
-          firstBQChild  = GetAsDOMNode(curNode);
-          lastBQChild   = GetAsDOMNode(curNode);
+          // If so, remember it and the first node we are taking out of it.
+          curBlockQuote = n->AsElement();
+          firstBQChild = curNode;
+          lastBQChild = curNode;
           break;
-        }
-        else if (useCSS)
-        {
-          NS_ENSURE_STATE(mHTMLEditor);
-          nsIAtom* marginProperty =
-            MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils,
-                                        GetAsDOMNode(curNode));
+        } else if (useCSS) {
+          nsIAtom& marginProperty =
+            MarginPropertyAtomForIndent(*mHTMLEditor->mHTMLCSSUtils, curNode);
           nsAutoString value;
-          NS_ENSURE_STATE(mHTMLEditor);
-          mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*n, *marginProperty,
+          mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*n, marginProperty,
                                                            value);
           float f;
           nsCOMPtr<nsIAtom> unit;
-          NS_ENSURE_STATE(mHTMLEditor);
           mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit));
-          if (f > 0 && !(nsHTMLEditUtils::IsList(curParent) && nsHTMLEditUtils::IsList(curNode)))
-          {
-            curBlockQuote = GetAsDOMNode(n);
-            firstBQChild  = GetAsDOMNode(curNode);
-            lastBQChild   = GetAsDOMNode(curNode);
+          if (f > 0 && !(nsHTMLEditUtils::IsList(curParent) &&
+                         nsHTMLEditUtils::IsList(curNode))) {
+            curBlockQuote = n->AsElement();
+            firstBQChild = curNode;
+            lastBQChild = curNode;
             curBlockQuoteIsIndentedWithCSS = true;
             break;
           }
         }
       }
 
-      if (!curBlockQuote)
-      {
-        // could not find an enclosing blockquote for this node.  handle list cases.
-        if (nsHTMLEditUtils::IsList(curParent))  // move node out of list
-        {
-          if (nsHTMLEditUtils::IsList(curNode))  // just unwrap this sublist
-          {
-            NS_ENSURE_STATE(mHTMLEditor);
-            res = mHTMLEditor->RemoveBlockContainer(GetAsDOMNode(curNode));
+      if (!curBlockQuote) {
+        // Couldn't find enclosing blockquote.  Handle list cases.
+        if (nsHTMLEditUtils::IsList(curParent)) {
+          // Move node out of list
+          if (nsHTMLEditUtils::IsList(curNode)) {
+            // Just unwrap this sublist
+            res = mHTMLEditor->RemoveBlockContainer(curNode);
             NS_ENSURE_SUCCESS(res, res);
           }
           // handled list item case above
-        }
-        else if (nsHTMLEditUtils::IsList(curNode)) // node is a list, but parent is non-list: move list items out
-        {
+        } else if (nsHTMLEditUtils::IsList(curNode)) {
+          // node is a list, but parent is non-list: move list items out
           nsCOMPtr<nsIContent> child = curNode->GetLastChild();
-          while (child)
-          {
-            if (nsHTMLEditUtils::IsListItem(child))
-            {
-              bool bOutOfList;
-              res = PopListItem(GetAsDOMNode(child), &bOutOfList);
+          while (child) {
+            if (nsHTMLEditUtils::IsListItem(child)) {
+              bool unused;
+              res = PopListItem(GetAsDOMNode(child), &unused);
               NS_ENSURE_SUCCESS(res, res);
-            }
-            else if (nsHTMLEditUtils::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.
-
-              NS_ENSURE_STATE(mHTMLEditor);
+            } else if (nsHTMLEditUtils::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.
+
               res = mHTMLEditor->MoveNode(child, curParent, offset + 1);
               NS_ENSURE_SUCCESS(res, res);
-            }
-            else
-            {
-              // delete any non- list items for now
-              NS_ENSURE_STATE(mHTMLEditor);
+            } else {
+              // Delete any non-list items for now
               res = mHTMLEditor->DeleteNode(child);
               NS_ENSURE_SUCCESS(res, res);
             }
             child = curNode->GetLastChild();
           }
-          // delete the now-empty list
-          NS_ENSURE_STATE(mHTMLEditor);
-          res = mHTMLEditor->RemoveBlockContainer(GetAsDOMNode(curNode));
+          // Delete the now-empty list
+          res = mHTMLEditor->RemoveBlockContainer(curNode);
           NS_ENSURE_SUCCESS(res, res);
-        }
-        else if (useCSS) {
-          nsCOMPtr<nsIDOMElement> element;
+        } else if (useCSS) {
+          nsCOMPtr<Element> element;
           nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(curNode);
-          if (textNode) {
+          if (curNode->GetAsText()) {
             // We want to outdent the parent of text nodes
-            nsCOMPtr<nsIDOMNode> parent;
-            textNode->GetParentNode(getter_AddRefs(parent));
-            element = do_QueryInterface(parent);
-          } else {
-            element = do_QueryInterface(curNode);
+            element = curNode->GetParentElement();
+          } else if (curNode->IsElement()) {
+            element = curNode->AsElement();
           }
           if (element) {
-            RelativeChangeIndentationOfElementNode(element, -1);
+            ChangeIndentation(*element, Change::minus);
           }
         }
       }
     }
-    if (curBlockQuote)
-    {
-      // we have a blockquote we haven't finished handling
-      res = OutdentPartOfBlock(curBlockQuote, firstBQChild, lastBQChild,
+    if (curBlockQuote) {
+      // We have a blockquote we haven't finished handling
+      res = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
                                curBlockQuoteIsIndentedWithCSS,
-                               address_of(rememberedLeftBQ),
-                               address_of(rememberedRightBQ));
+                               getter_AddRefs(rememberedLeftBQ),
+                               getter_AddRefs(rememberedRightBQ));
       NS_ENSURE_SUCCESS(res, res);
     }
   }
-  // make sure selection didn't stick to last piece of content in old bq
-  // (only a problem for collapsed selections)
+  // Make sure selection didn't stick to last piece of content in old bq (only
+  // a problem for collapsed selections)
   if (rememberedLeftBQ || rememberedRightBQ) {
-    if (aSelection->Collapsed()) {
-      // push selection past end of rememberedLeftBQ
-      nsCOMPtr<nsIDOMNode> sNode;
-      int32_t sOffset;
-      NS_ENSURE_STATE(mHTMLEditor);
-      mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(sNode), &sOffset);
+    if (aSelection.Collapsed()) {
+      // Push selection past end of rememberedLeftBQ
+      NS_ENSURE_TRUE(aSelection.GetRangeAt(0), NS_OK);
+      nsCOMPtr<nsINode> startNode = aSelection.GetRangeAt(0)->GetStartParent();
+      int32_t startOffset = aSelection.GetRangeAt(0)->StartOffset();
       if (rememberedLeftBQ &&
-          ((sNode == rememberedLeftBQ) || nsEditorUtils::IsDescendantOf(sNode, rememberedLeftBQ)))
-      {
-        // selection is inside rememberedLeftBQ - push it past it.
-        sNode = nsEditor::GetNodeLocation(rememberedLeftBQ, &sOffset);
-        sOffset++;
-        aSelection->Collapse(sNode, sOffset);
-      }
-      // and pull selection before beginning of rememberedRightBQ
-      NS_ENSURE_STATE(mHTMLEditor);
-      mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(sNode), &sOffset);
+          (startNode == rememberedLeftBQ ||
+           nsEditorUtils::IsDescendantOf(startNode, rememberedLeftBQ))) {
+        // Selection is inside rememberedLeftBQ - push it past it.
+        startNode = rememberedLeftBQ->GetParentNode();
+        startOffset = startNode ? 1 + startNode->IndexOf(rememberedLeftBQ) : 0;
+        aSelection.Collapse(startNode, startOffset);
+      }
+      // And pull selection before beginning of rememberedRightBQ
+      startNode = aSelection.GetRangeAt(0)->GetStartParent();
+      startOffset = aSelection.GetRangeAt(0)->StartOffset();
       if (rememberedRightBQ &&
-          ((sNode == rememberedRightBQ) || nsEditorUtils::IsDescendantOf(sNode, rememberedRightBQ)))
-      {
-        // selection is inside rememberedRightBQ - push it before it.
-        sNode = nsEditor::GetNodeLocation(rememberedRightBQ, &sOffset);
-        aSelection->Collapse(sNode, sOffset);
+          (startNode == rememberedRightBQ ||
+           nsEditorUtils::IsDescendantOf(startNode, rememberedRightBQ))) {
+        // Selection is inside rememberedRightBQ - push it before it.
+        startNode = rememberedRightBQ->GetParentNode();
+        startOffset = startNode ? startNode->IndexOf(rememberedRightBQ) : -1;
+        aSelection.Collapse(startNode, startOffset);
       }
     }
     return NS_OK;
   }
-  return res;
+  return NS_OK;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // RemovePartOfBlock: Split aBlock and move aStartChild to aEndChild out of
 //                    aBlock.
 nsresult
 nsHTMLEditRules::RemovePartOfBlock(Element& aBlock,
                                    nsIContent& aStartChild,
                                    nsIContent& aEndChild)
 {
-  nsresult res = SplitBlock(aBlock.AsDOMNode(), aStartChild.AsDOMNode(),
-                            aEndChild.AsDOMNode());
-  NS_ENSURE_SUCCESS(res, res);
+  SplitBlock(aBlock, aStartChild, aEndChild);
   // Get rid of part of blockquote we are outdenting
 
   NS_ENSURE_STATE(mHTMLEditor);
-  return mHTMLEditor->RemoveBlockContainer(aBlock.AsDOMNode());
+  nsresult res = mHTMLEditor->RemoveBlockContainer(aBlock);
+  NS_ENSURE_SUCCESS(res, res);
+
+  return NS_OK;
+}
+
+void
+nsHTMLEditRules::SplitBlock(Element& aBlock,
+                            nsIContent& aStartChild,
+                            nsIContent& aEndChild,
+                            nsIContent** aOutLeftNode,
+                            nsIContent** aOutRightNode,
+                            nsIContent** aOutMiddleNode)
+{
+  // aStartChild and aEndChild must be exclusive descendants of aBlock
+  MOZ_ASSERT(nsEditorUtils::IsDescendantOf(&aStartChild, &aBlock) &&
+             nsEditorUtils::IsDescendantOf(&aEndChild, &aBlock));
+  NS_ENSURE_TRUE_VOID(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  // Get split point location
+  OwningNonNull<nsIContent> startParent = *aStartChild.GetParent();
+  int32_t startOffset = startParent->IndexOf(&aStartChild);
+
+  // Do the splits!
+  nsCOMPtr<nsIContent> newMiddleNode1;
+  mHTMLEditor->SplitNodeDeep(aBlock, startParent, startOffset,
+                             nsHTMLEditor::EmptyContainers::no,
+                             aOutLeftNode, getter_AddRefs(newMiddleNode1));
+
+  // Get split point location
+  OwningNonNull<nsIContent> endParent = *aEndChild.GetParent();
+  // +1 because we want to be after the child
+  int32_t endOffset = 1 + endParent->IndexOf(&aEndChild);
+
+  // Do the splits!
+  nsCOMPtr<nsIContent> newMiddleNode2;
+  mHTMLEditor->SplitNodeDeep(aBlock, endParent, endOffset,
+                             nsHTMLEditor::EmptyContainers::no,
+                             getter_AddRefs(newMiddleNode2), aOutRightNode);
+
+  if (aOutMiddleNode) {
+    if (newMiddleNode2) {
+      newMiddleNode2.forget(aOutMiddleNode);
+    } else {
+      newMiddleNode1.forget(aOutMiddleNode);
+    }
+  }
 }
 
 nsresult
-nsHTMLEditRules::SplitBlock(nsIDOMNode *aBlock,
-                            nsIDOMNode *aStartChild,
-                            nsIDOMNode *aEndChild,
-                            nsCOMPtr<nsIDOMNode> *aLeftNode,
-                            nsCOMPtr<nsIDOMNode> *aRightNode,
-                            nsCOMPtr<nsIDOMNode> *aMiddleNode)
-{
-  NS_ENSURE_TRUE(aBlock && aStartChild && aEndChild, NS_ERROR_NULL_POINTER);
-
-  nsCOMPtr<nsIContent> leftNode, rightNode;
-  int32_t startOffset, endOffset;
-
-  // get split point location
-  nsCOMPtr<nsIDOMNode> startParent = nsEditor::GetNodeLocation(aStartChild, &startOffset);
-
-  // do the splits!
-  nsCOMPtr<nsIContent> block = do_QueryInterface(aBlock);
-  NS_ENSURE_STATE(block || !aBlock);
-  nsCOMPtr<nsIContent> startParentContent = do_QueryInterface(startParent);
-  NS_ENSURE_STATE(startParentContent || !startParent);
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->SplitNodeDeep(*block, *startParentContent, startOffset,
-                             nsHTMLEditor::EmptyContainers::no,
-                             getter_AddRefs(leftNode),
-                             getter_AddRefs(rightNode));
-  if (rightNode) {
-    aBlock = GetAsDOMNode(rightNode);
-  }
-
-  // remember left portion of block if caller requested
-  if (aLeftNode)
-    *aLeftNode = GetAsDOMNode(leftNode);
-
-  // get split point location
-  nsCOMPtr<nsIDOMNode> endParent = nsEditor::GetNodeLocation(aEndChild, &endOffset);
-  endOffset++;  // want to be after lastBQChild
-
-  // do the splits!
-  nsCOMPtr<nsIContent> endParentContent = do_QueryInterface(endParent);
-  NS_ENSURE_STATE(endParentContent || !endParent);
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->SplitNodeDeep(*block, *endParentContent, endOffset,
-                             nsHTMLEditor::EmptyContainers::no,
-                             getter_AddRefs(leftNode),
-                             getter_AddRefs(rightNode));
-  if (leftNode) {
-    aBlock = GetAsDOMNode(leftNode);
-  }
-
-  // remember right portion of block if caller requested
-  if (aRightNode)
-    *aRightNode = GetAsDOMNode(rightNode);
-
-  if (aMiddleNode)
-    *aMiddleNode = aBlock;
+nsHTMLEditRules::OutdentPartOfBlock(Element& aBlock,
+                                    nsIContent& aStartChild,
+                                    nsIContent& aEndChild,
+                                    bool aIsBlockIndentedWithCSS,
+                                    nsIContent** aOutLeftNode,
+                                    nsIContent** aOutRightNode)
+{
+  MOZ_ASSERT(aOutLeftNode && aOutRightNode);
+
+  nsCOMPtr<nsIContent> middleNode;
+  SplitBlock(aBlock, aStartChild, aEndChild, aOutLeftNode, aOutRightNode,
+             getter_AddRefs(middleNode));
+
+  NS_ENSURE_STATE(middleNode);
+
+  if (!aIsBlockIndentedWithCSS) {
+    NS_ENSURE_STATE(mHTMLEditor);
+    nsresult res =
+      mHTMLEditor->RemoveBlockContainer(*middleNode);
+    NS_ENSURE_SUCCESS(res, res);
+  } else if (middleNode->IsElement()) {
+    // We do nothing if middleNode isn't an element
+    nsresult res = ChangeIndentation(*middleNode->AsElement(), Change::minus);
+    NS_ENSURE_SUCCESS(res, res);
+  }
 
   return NS_OK;
 }
 
-nsresult
-nsHTMLEditRules::OutdentPartOfBlock(nsIDOMNode *aBlock,
-                                    nsIDOMNode *aStartChild,
-                                    nsIDOMNode *aEndChild,
-                                    bool aIsBlockIndentedWithCSS,
-                                    nsCOMPtr<nsIDOMNode> *aLeftNode,
-                                    nsCOMPtr<nsIDOMNode> *aRightNode)
-{
-  nsCOMPtr<nsIDOMNode> middleNode;
-  nsresult res = SplitBlock(aBlock, aStartChild, aEndChild,
-                            aLeftNode,
-                            aRightNode,
-                            address_of(middleNode));
-  NS_ENSURE_SUCCESS(res, res);
-  if (aIsBlockIndentedWithCSS) {
-    res = RelativeChangeIndentationOfElementNode(middleNode, -1);
-  } else {
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->RemoveBlockContainer(middleNode);
-  }
-  return res;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // ConvertListType:  convert list type and list item type.
 //
 //
 nsresult
-nsHTMLEditRules::ConvertListType(nsIDOMNode* aList,
-                                 nsCOMPtr<nsIDOMNode>* outList,
-                                 nsIAtom* aListType,
-                                 nsIAtom* aItemType)
-{
-  MOZ_ASSERT(aListType);
-  MOZ_ASSERT(aItemType);
-
-  NS_ENSURE_TRUE(aList && outList, NS_ERROR_NULL_POINTER);
-  nsCOMPtr<Element> list = do_QueryInterface(aList);
-  NS_ENSURE_STATE(list);
-
-  nsCOMPtr<dom::Element> outNode;
-  nsresult rv = ConvertListType(list, getter_AddRefs(outNode), aListType, aItemType);
-  *outList = outNode ? outNode->AsDOMNode() : nullptr;
-  return rv;
-}
-
-nsresult
 nsHTMLEditRules::ConvertListType(Element* aList,
-                                 dom::Element** aOutList,
+                                 Element** aOutList,
                                  nsIAtom* aListType,
                                  nsIAtom* aItemType)
 {
   MOZ_ASSERT(aList);
   MOZ_ASSERT(aOutList);
   MOZ_ASSERT(aListType);
   MOZ_ASSERT(aItemType);
 
@@ -4447,29 +4325,26 @@ nsHTMLEditRules::ConvertListType(Element
 
 
 ///////////////////////////////////////////////////////////////////////////
 // CreateStyleForInsertText:  take care of clearing and setting appropriate
 //                            style nodes for text insertion.
 //
 //
 nsresult
-nsHTMLEditRules::CreateStyleForInsertText(Selection* aSelection,
-                                          nsIDOMDocument *aDoc)
-{
-  MOZ_ASSERT(aSelection && aDoc && mHTMLEditor->mTypeInState);
-
+nsHTMLEditRules::CreateStyleForInsertText(Selection& aSelection,
+                                          nsIDocument& aDoc)
+{
+  MOZ_ASSERT(mHTMLEditor->mTypeInState);
+
+  nsresult res;
   bool weDidSomething = false;
-  nsCOMPtr<nsIDOMNode> node, tmp;
-  int32_t offset;
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsresult res = mHTMLEditor->GetStartNodeAndOffset(aSelection,
-                                                    getter_AddRefs(node),
-                                                    &offset);
-  NS_ENSURE_SUCCESS(res, res);
+  NS_ENSURE_STATE(aSelection.GetRangeAt(0));
+  nsCOMPtr<nsINode> node = aSelection.GetRangeAt(0)->GetStartParent();
+  int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
 
   // next examine our present style and make sure default styles are either
   // present or explicitly overridden.  If neither, add the default style to
   // the TypeInState
   int32_t length = mHTMLEditor->mDefaultStyles.Length();
   for (int32_t j = 0; j < length; j++) {
     PropItem* propItem = mHTMLEditor->mDefaultStyles[j];
     MOZ_ASSERT(propItem);
@@ -4492,19 +4367,18 @@ nsHTMLEditRules::CreateStyleForInsertTex
 
     if (!bAny) {
       // no style set for this prop/attr
       mHTMLEditor->mTypeInState->SetProp(propItem->tag, propItem->attr,
                                          propItem->value);
     }
   }
 
-  nsCOMPtr<nsIDOMElement> rootElement;
-  res = aDoc->GetDocumentElement(getter_AddRefs(rootElement));
-  NS_ENSURE_SUCCESS(res, res);
+  nsCOMPtr<Element> rootElement = aDoc.GetRootElement();
+  NS_ENSURE_STATE(rootElement);
 
   // process clearing any styles first
   nsAutoPtr<PropItem> item(mHTMLEditor->mTypeInState->TakeClearProperty());
   while (item && node != rootElement) {
     NS_ENSURE_STATE(mHTMLEditor);
     res = mHTMLEditor->ClearStyle(address_of(node), &offset,
                                   item->tag, &item->attr);
     NS_ENSURE_SUCCESS(res, res);
@@ -4514,331 +4388,292 @@ nsHTMLEditRules::CreateStyleForInsertTex
 
   // then process setting any styles
   int32_t relFontSize = mHTMLEditor->mTypeInState->TakeRelativeFontSize();
   item = mHTMLEditor->mTypeInState->TakeSetProperty();
 
   if (item || relFontSize) {
     // we have at least one style to add; make a new text node to insert style
     // nodes above.
-    if (mHTMLEditor->IsTextNode(node)) {
+    if (RefPtr<Text> text = node->GetAsText()) {
       // if we are in a text node, split it
       NS_ENSURE_STATE(mHTMLEditor);
-      nsCOMPtr<nsIContent> content = do_QueryInterface(node);
-      NS_ENSURE_STATE(content || !node);
-      offset = mHTMLEditor->SplitNodeDeep(*content, *content, offset);
+      offset = mHTMLEditor->SplitNodeDeep(*text, *text, offset);
       NS_ENSURE_STATE(offset != -1);
-      node->GetParentNode(getter_AddRefs(tmp));
-      node = tmp;
+      node = node->GetParentNode();
     }
     if (!mHTMLEditor->IsContainer(node)) {
       return NS_OK;
     }
-    nsCOMPtr<nsIDOMNode> newNode;
-    nsCOMPtr<nsIDOMText> nodeAsText;
-    res = aDoc->CreateTextNode(EmptyString(), getter_AddRefs(nodeAsText));
-    NS_ENSURE_SUCCESS(res, res);
-    NS_ENSURE_TRUE(nodeAsText, NS_ERROR_NULL_POINTER);
-    newNode = do_QueryInterface(nodeAsText);
+    OwningNonNull<Text> newNode = aDoc.CreateTextNode(EmptyString());
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->InsertNode(newNode, node, offset);
+    res = mHTMLEditor->InsertNode(newNode, *node, offset);
     NS_ENSURE_SUCCESS(res, res);
     node = newNode;
     offset = 0;
     weDidSomething = true;
 
     if (relFontSize) {
       // dir indicated bigger versus smaller.  1 = bigger, -1 = smaller
-      int32_t dir = relFontSize > 0 ? 1 : -1;
+      nsHTMLEditor::FontSize dir = relFontSize > 0 ?
+        nsHTMLEditor::FontSize::incr : nsHTMLEditor::FontSize::decr;
       for (int32_t j = 0; j < DeprecatedAbs(relFontSize); j++) {
         NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->RelativeFontChangeOnTextNode(dir, nodeAsText,
-                                                        0, -1);
+        res = mHTMLEditor->RelativeFontChangeOnTextNode(dir, newNode, 0, -1);
         NS_ENSURE_SUCCESS(res, res);
       }
     }
 
     while (item) {
       NS_ENSURE_STATE(mHTMLEditor);
-      nsCOMPtr<nsIContent> content = do_QueryInterface(node);
-      NS_ENSURE_STATE(content || !node);
-      res = mHTMLEditor->SetInlinePropertyOnNode(*content, *item->tag,
-                                                 &item->attr, item->value);
+      res = mHTMLEditor->SetInlinePropertyOnNode(*node->AsContent(),
+                                                 *item->tag, &item->attr,
+                                                 item->value);
       NS_ENSURE_SUCCESS(res, res);
       item = mHTMLEditor->mTypeInState->TakeSetProperty();
     }
   }
   if (weDidSomething) {
-    return aSelection->Collapse(node, offset);
+    return aSelection.Collapse(node, offset);
   }
 
   return NS_OK;
 }
 
 
-///////////////////////////////////////////////////////////////////////////
-// IsEmptyBlock: figure out if aNode is (or is inside) an empty block.
-//               A block can have children and still be considered empty,
-//               if the children are empty or non-editable.
-//
+/**
+ * Figure out if aNode is (or is inside) an empty block.  A block can have
+ * children and still be considered empty, if the children are empty or
+ * non-editable.
+ */
 nsresult
-nsHTMLEditRules::IsEmptyBlock(nsIDOMNode *aNode,
-                              bool *outIsEmptyBlock,
-                              bool aMozBRDoesntCount,
-                              bool aListItemsNotEmpty)
-{
-  NS_ENSURE_TRUE(aNode && outIsEmptyBlock, NS_ERROR_NULL_POINTER);
-  *outIsEmptyBlock = true;
-
-//  nsresult res = NS_OK;
-  nsCOMPtr<nsIDOMNode> nodeToTest;
-  if (IsBlockNode(aNode)) nodeToTest = do_QueryInterface(aNode);
-//  else nsCOMPtr<nsIDOMElement> block;
-//  looks like I forgot to finish this.  Wonder what I was going to do?
-
-  NS_ENSURE_TRUE(nodeToTest, NS_ERROR_NULL_POINTER);
-  return mHTMLEditor->IsEmptyNode(nodeToTest, outIsEmptyBlock,
-                     aMozBRDoesntCount, aListItemsNotEmpty);
+nsHTMLEditRules::IsEmptyBlock(Element& aNode,
+                              bool* aOutIsEmptyBlock,
+                              MozBRCounts aMozBRCounts)
+{
+  MOZ_ASSERT(aOutIsEmptyBlock);
+  *aOutIsEmptyBlock = true;
+
+  NS_ENSURE_TRUE(IsBlockNode(aNode), NS_ERROR_NULL_POINTER);
+
+  return mHTMLEditor->IsEmptyNode(aNode.AsDOMNode(), aOutIsEmptyBlock,
+                                  aMozBRCounts == MozBRCounts::yes ? false
+                                                                   : true);
 }
 
 
 nsresult
-nsHTMLEditRules::WillAlign(Selection* aSelection,
-                           const nsAString *alignType,
-                           bool *aCancel,
-                           bool *aHandled)
-{
-  if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
-
-  WillInsert(*aSelection, aCancel);
-
-  // initialize out param
-  // we want to ignore result of WillInsert()
+nsHTMLEditRules::WillAlign(Selection& aSelection,
+                           const nsAString& aAlignType,
+                           bool* aCancel,
+                           bool* aHandled)
+{
+  MOZ_ASSERT(aCancel && aHandled);
+
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  WillInsert(aSelection, aCancel);
+
+  // Initialize out param.  We want to ignore result of WillInsert().
   *aCancel = false;
   *aHandled = false;
 
-  nsresult res = NormalizeSelection(aSelection);
-  NS_ENSURE_SUCCESS(res, res);
-  nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
-
-  // 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
+  nsresult rv = NormalizeSelection(&aSelection);
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsAutoSelectionReset selectionResetter(&aSelection, mHTMLEditor);
+
+  // 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;
-  res = GetNodesFromSelection(*aSelection, EditAction::align, nodeArray);
-  NS_ENSURE_SUCCESS(res, res);
-
-  // if we don't have any nodes, or we have only a single br, then we are
-  // creating an empty alignment div.  We have to do some different things for these.
-  bool emptyDiv = false;
-  int32_t listCount = nodeArray.Length();
-  if (!listCount) emptyDiv = true;
-  if (listCount == 1)
-  {
-    OwningNonNull<nsINode> theNode = nodeArray[0];
-
-    if (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(theNode))) {
-      // the node is a table element, an horiz rule, a paragraph, a div
-      // or a section header; in HTML 4, it can directly carry the ALIGN
-      // attribute and we don't need to make a div! If we are in CSS mode,
-      // all the work is done in AlignBlock
-      nsCOMPtr<nsIDOMElement> theElem = do_QueryInterface(theNode);
-      res = AlignBlock(theElem, alignType, true);
-      NS_ENSURE_SUCCESS(res, res);
+  rv = GetNodesFromSelection(aSelection, EditAction::align, nodeArray);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // If we don't have any nodes, or we have only a single br, then we are
+  // creating an empty alignment div.  We have to do some different things for
+  // these.
+  bool emptyDiv = nodeArray.IsEmpty();
+  if (nodeArray.Length() == 1) {
+    OwningNonNull<nsINode> node = nodeArray[0];
+
+    if (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(node))) {
+      // 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 make a div! If we are in CSS mode, all the work is done
+      // in AlignBlock
+      rv = AlignBlock(*node->AsElement(), aAlignType, ContentsOnly::yes);
+      NS_ENSURE_SUCCESS(rv, rv);
       return NS_OK;
     }
 
-    if (nsTextEditUtils::IsBreak(theNode))
-    {
-      // The special case emptyDiv code (below) that consumes BRs can
-      // cause tables to split if the start node of the selection is
-      // not in a table cell or caption, for example parent is a <tr>.
-      // Avoid this unnecessary splitting if possible by leaving emptyDiv
-      // FALSE so that we fall through to the normal case alignment code.
+    if (nsTextEditUtils::IsBreak(node)) {
+      // The special case emptyDiv code (below) that consumes BRs can cause
+      // tables to split if the start node of the selection is not in a table
+      // cell or caption, for example parent is a <tr>.  Avoid this unnecessary
+      // splitting if possible by leaving emptyDiv FALSE so that we fall
+      // through to the normal case alignment code.
       //
-      // XXX: It seems a little error prone for the emptyDiv special
-      //      case code to assume that the start node of the selection
-      //      is the parent of the single node in the nodeArray, as
-      //      the paragraph above points out. Do we rely on the selection
-      //      start node because of the fact that nodeArray can be empty?
-      //      We should probably revisit this issue. - kin
-
-      nsCOMPtr<nsIDOMNode> parent;
-      int32_t offset;
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
-
-      if (!nsHTMLEditUtils::IsTableElement(parent) || nsHTMLEditUtils::IsTableCellOrCaption(parent))
-        emptyDiv = true;
-    }
-  }
-  if (emptyDiv)
-  {
-    nsCOMPtr<nsIDOMNode> brNode, sib;
-    NS_NAMED_LITERAL_STRING(divType, "div");
-
-    NS_ENSURE_STATE(aSelection->GetRangeAt(0));
-    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
-    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
+      // XXX: It seems a little error prone for the emptyDiv special case code
+      // to assume that the start node of the selection is the parent of the
+      // single node in the nodeArray, as the paragraph above points out. Do we
+      // rely on the selection start node because of the fact that nodeArray
+      // can be empty?  We should probably revisit this issue. - kin
+
+      NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
+                      aSelection.GetRangeAt(0)->GetStartParent());
+      OwningNonNull<nsINode> parent =
+        *aSelection.GetRangeAt(0)->GetStartParent();
+
+      emptyDiv = !nsHTMLEditUtils::IsTableElement(parent) ||
+                 nsHTMLEditUtils::IsTableCellOrCaption(parent);
+    }
+  }
+  if (emptyDiv) {
+    nsCOMPtr<nsINode> parent =
+      aSelection.GetRangeAt(0) ? aSelection.GetRangeAt(0)->GetStartParent()
+                               : nullptr;
     NS_ENSURE_STATE(parent);
-
-    res = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
-    NS_ENSURE_SUCCESS(res, res);
-    // consume a trailing br, if any.  This is to keep an alignment from
+    int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
+
+    rv = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
+    NS_ENSURE_SUCCESS(rv, rv);
+    // Consume a trailing br, if any.  This is to keep an alignment from
     // creating extra lines, if possible.
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetNextHTMLNode(GetAsDOMNode(parent), offset,
-                                       address_of(brNode));
-    NS_ENSURE_SUCCESS(res, res);
-    if (brNode && nsTextEditUtils::IsBreak(brNode))
-    {
-      // 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 its safe to consume it.
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->GetNextHTMLSibling(GetAsDOMNode(parent), offset,
-                                            address_of(sib));
-      NS_ENSURE_SUCCESS(res, res);
-      if (!IsBlockNode(sib))
-      {
-        NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->DeleteNode(brNode);
-        NS_ENSURE_SUCCESS(res, res);
-      }
-    }
-    NS_ENSURE_STATE(mHTMLEditor);
-    nsCOMPtr<Element> theDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, parent,
-                                                       offset);
-    NS_ENSURE_STATE(theDiv);
-    // remember our new block for postprocessing
-    mNewBlock = GetAsDOMNode(theDiv);
-    // set up the alignment on the div, using HTML or CSS
-    nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(theDiv);
-    res = AlignBlock(divElem, alignType, true);
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<nsIContent> brContent =
+      mHTMLEditor->GetNextHTMLNode(parent, offset);
+    if (brContent && nsTextEditUtils::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 = mHTMLEditor->GetNextHTMLSibling(parent,
+                                                                     offset);
+      if (sibling && !IsBlockNode(*sibling)) {
+        rv = mHTMLEditor->DeleteNode(brContent);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+    }
+    nsCOMPtr<Element> div = mHTMLEditor->CreateNode(nsGkAtoms::div, parent,
+                                                    offset);
+    NS_ENSURE_STATE(div);
+    // 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);
     *aHandled = true;
-    // put in a moz-br so that it won't get deleted
-    res = CreateMozBR(GetAsDOMNode(theDiv), 0);
-    NS_ENSURE_SUCCESS(res, res);
-    res = aSelection->Collapse(theDiv, 0);
-    selectionResetter.Abort();  // don't reset our selection in this case.
-    return res;
+    // Put in a moz-br so that it won't get deleted
+    rv = CreateMozBR(div->AsDOMNode(), 0);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = aSelection.Collapse(div, 0);
+    // Don't reset our selection in this case.
+    selectionResetter.Abort();
+    NS_ENSURE_SUCCESS(rv, rv);
+    return NS_OK;
   }
 
   // Next we detect all the transitions in the array, where a transition
   // means that adjacent nodes in the array don't have the same parent.
 
   nsTArray<bool> transitionList;
   MakeTransitionList(nodeArray, transitionList);
 
-  // Ok, now go through all the nodes and give them an align attrib or put them in a div,
-  // or whatever is appropriate.  Wohoo!
-
-  nsCOMPtr<nsINode> curParent;
+  // 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 = mHTMLEditor->IsCSSEnabled();
-  for (int32_t i = 0; i < listCount; ++i) {
-    // here's where we actually figure out what to do
-    nsCOMPtr<nsIDOMNode> curNode = nodeArray[i]->AsDOMNode();
-    nsCOMPtr<nsIContent> curContent = do_QueryInterface(curNode);
-    NS_ENSURE_STATE(curContent);
+  for (size_t i = 0; i < nodeArray.Length(); i++) {
+    auto& curNode = nodeArray[i];
+    // Here's where we actually figure out what to do
 
     // Ignore all non-editable nodes.  Leave them be.
-    if (!mHTMLEditor->IsEditable(curNode)) continue;
-
-    curParent = curContent->GetParentNode();
-    int32_t offset = curParent ? curParent->IndexOf(curContent) : -1;
-
-    // the node is a table element, an horiz rule, 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 (nsHTMLEditUtils::SupportsAlignAttr(curNode))
-    {
-      nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(curNode);
-      res = AlignBlock(curElem, alignType, false);
-      NS_ENSURE_SUCCESS(res, res);
-      // clear out curDiv so that we don't put nodes after this one into it
-      curDiv = 0;
+    if (!mHTMLEditor->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 (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(curNode))) {
+      rv = AlignBlock(*curNode->AsElement(), aAlignType, ContentsOnly::no);
+      NS_ENSURE_SUCCESS(rv, rv);
+      // Clear out curDiv so that we don't put nodes after this one into it
+      curDiv = nullptr;
       continue;
     }
 
-    // Skip insignificant formatting text nodes to prevent
-    // unnecessary structure splitting!
+    nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
+    int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
+
+    // Skip insignificant formatting text nodes to prevent unnecessary
+    // structure splitting!
     bool isEmptyTextNode = false;
-    if (nsEditor::IsTextNode(curNode) &&
-       ((nsHTMLEditUtils::IsTableElement(curParent) &&
-         !nsHTMLEditUtils::IsTableCellOrCaption(GetAsDOMNode(curParent))) ||
-        nsHTMLEditUtils::IsList(curParent) ||
-        (NS_SUCCEEDED(mHTMLEditor->IsEmptyNode(curNode, &isEmptyTextNode)) && isEmptyTextNode)))
+    if (curNode->GetAsText() &&
+        ((nsHTMLEditUtils::IsTableElement(curParent) &&
+          !nsHTMLEditUtils::IsTableCellOrCaption(*curParent)) ||
+         nsHTMLEditUtils::IsList(curParent) ||
+         (NS_SUCCEEDED(mHTMLEditor->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 ( nsHTMLEditUtils::IsListItem(curNode)
-         || nsHTMLEditUtils::IsList(curNode))
-    {
-      res = RemoveAlignment(curNode, *alignType, true);
-      NS_ENSURE_SUCCESS(res, res);
+    }
+
+    // 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 (nsHTMLEditUtils::IsListItem(curNode) ||
+        nsHTMLEditUtils::IsList(curNode)) {
+      rv = RemoveAlignment(GetAsDOMNode(curNode), aAlignType, true);
+      NS_ENSURE_SUCCESS(rv, rv);
       if (useCSS) {
-        nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(curNode);
-        NS_NAMED_LITERAL_STRING(attrName, "align");
-        int32_t count;
-        mHTMLEditor->mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(curNode, nullptr,
-                                                                &attrName, alignType,
-                                                                &count, false);
-        curDiv = 0;
+        mHTMLEditor->mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(
+            curNode->AsElement(), nullptr, &NS_LITERAL_STRING("align"),
+            &aAlignType, false);
+        curDiv = nullptr;
         continue;
-      }
-      else if (nsHTMLEditUtils::IsList(curParent)) {
-        // if we don't use CSS, add a contraint to list element : they have
-        // to be inside another list, ie >= second level of nesting
-        res = AlignInnerBlocks(*curContent, alignType);
-        NS_ENSURE_SUCCESS(res, res);
-        curDiv = 0;
+      } else if (nsHTMLEditUtils::IsList(curParent)) {
+        // 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);
+        curDiv = nullptr;
         continue;
       }
-      // 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[i])
-    {
+      // 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[i]) {
       // First, check that our element can contain a div.
       if (!mEditor->CanContainTag(*curParent, *nsGkAtoms::div)) {
-        return NS_OK; // cancelled
-      }
-
-      res = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
-      NS_ENSURE_SUCCESS(res, res);
-      NS_ENSURE_STATE(mHTMLEditor);
+        // Cancelled
+        return NS_OK;
+      }
+
+      rv = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
+      NS_ENSURE_SUCCESS(rv, rv);
       curDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, curParent, offset);
       NS_ENSURE_STATE(curDiv);
-      // remember our new block for postprocessing
-      mNewBlock = GetAsDOMNode(curDiv);
-      // set up the alignment on the div
-      nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(curDiv);
-      res = AlignBlock(divElem, alignType, true);
-      //nsAutoString attr(NS_LITERAL_STRING("align"));
-      //res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
-      //NS_ENSURE_SUCCESS(res, res);
-      // curDiv is now the correct thing to put curNode in
-    }
-
-    // tuck the node into the end of the active div
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->MoveNode(curContent, curDiv, -1);
-    NS_ENSURE_SUCCESS(res, res);
-  }
-
-  return res;
+      // Remember our new block for postprocessing
+      mNewBlock = curDiv;
+      // Set up the alignment on the div
+      rv = AlignBlock(*curDiv, aAlignType, ContentsOnly::yes);
+    }
+
+    NS_ENSURE_STATE(curNode->IsContent());
+
+    // Tuck the node into the end of the active div
+    rv = mHTMLEditor->MoveNode(curNode->AsContent(), curDiv, -1);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // AlignInnerBlocks: Align inside table cells or list items
 //
 nsresult
 nsHTMLEditRules::AlignInnerBlocks(nsINode& aNode, const nsAString* alignType)
@@ -4935,17 +4770,17 @@ nsHTMLEditRules::AlignBlockContents(nsID
 nsresult
 nsHTMLEditRules::CheckForEmptyBlock(nsINode* aStartNode,
                                     Element* aBodyNode,
                                     Selection* aSelection,
                                     nsIEditor::EDirection aAction,
                                     bool* aHandled)
 {
   // If the editing host is an inline element, bail out early.
-  if (IsInlineNode(GetAsDOMNode(aBodyNode))) {
+  if (aBodyNode && IsInlineNode(*aBodyNode)) {
     return NS_OK;
   }
   NS_ENSURE_STATE(mHTMLEditor);
   nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
 
   // If we are inside an empty block, delete it.  Note: do NOT delete table
   // elements this way.
   nsCOMPtr<Element> block = mHTMLEditor->GetBlock(*aStartNode);
@@ -5027,65 +4862,49 @@ nsHTMLEditRules::CheckForEmptyBlock(nsIN
     NS_ENSURE_STATE(mHTMLEditor);
     res = mHTMLEditor->DeleteNode(emptyBlock);
     *aHandled = true;
     NS_ENSURE_SUCCESS(res, res);
   }
   return NS_OK;
 }
 
-nsresult
-nsHTMLEditRules::CheckForInvisibleBR(nsIDOMNode *aBlock,
-                                     BRLocation aWhere,
-                                     nsCOMPtr<nsIDOMNode> *outBRNode,
+Element*
+nsHTMLEditRules::CheckForInvisibleBR(Element& aBlock, BRLocation aWhere,
                                      int32_t aOffset)
 {
-  nsCOMPtr<nsINode> block = do_QueryInterface(aBlock);
-  NS_ENSURE_TRUE(block && outBRNode, NS_ERROR_NULL_POINTER);
-  *outBRNode = nullptr;
-
-  nsCOMPtr<nsIDOMNode> testNode;
+  nsCOMPtr<nsINode> testNode;
   int32_t testOffset = 0;
-  bool runTest = false;
-
-  if (aWhere == kBlockEnd)
-  {
-    nsCOMPtr<nsIDOMNode> rightmostNode =
-      // no block crossing
-      GetAsDOMNode(mHTMLEditor->GetRightmostChild(block, true));
-
-    if (rightmostNode)
-    {
-      int32_t nodeOffset;
-      nsCOMPtr<nsIDOMNode> nodeParent = nsEditor::GetNodeLocation(rightmostNode,
-                                                                  &nodeOffset);
-      runTest = true;
-      testNode = nodeParent;
-      // use offset + 1, because we want the last node included in our
-      // evaluation
-      testOffset = nodeOffset + 1;
-    }
-  }
-  else if (aOffset)
-  {
-    runTest = true;
-    testNode = aBlock;
-    // we'll check everything to the left of the input position
+
+  if (aWhere == BRLocation::blockEnd) {
+    // No block crossing
+    nsCOMPtr<nsIContent> rightmostNode =
+      mHTMLEditor->GetRightmostChild(&aBlock, true);
+
+    if (!rightmostNode) {
+      return nullptr;
+    }
+
+    testNode = rightmostNode->GetParentNode();
+    // Use offset + 1, so last node is included in our evaluation
+    testOffset = testNode->IndexOf(rightmostNode) + 1;
+  } else if (aOffset) {
+    testNode = &aBlock;
+    // We'll check everything to the left of the input position
     testOffset = aOffset;
-  }
-
-  if (runTest)
-  {
-    nsWSRunObject wsTester(mHTMLEditor, testNode, testOffset);
-    if (WSType::br == wsTester.mStartReason) {
-      *outBRNode = GetAsDOMNode(wsTester.mStartReasonNode);
-    }
-  }
-
-  return NS_OK;
+  } else {
+    return nullptr;
+  }
+
+  nsWSRunObject wsTester(mHTMLEditor, testNode, testOffset);
+  if (WSType::br == wsTester.mStartReason) {
+    return wsTester.mStartReasonNode->AsElement();
+  }
+
+  return nullptr;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // GetInnerContent: aLists and aTables allow the caller to specify what kind of
 //                  content to "look inside".  If aTables is Tables::yes, look
 //                  inside any table content, and insert the inner content into
 //                  the supplied issupportsarray at offset aIndex.  Similarly
@@ -5107,190 +4926,148 @@ nsHTMLEditRules::GetInnerContent(nsINode
       GetInnerContent(*node, aOutArrayOfNodes, aIndex, aLists, aTables);
     } else {
       aOutArrayOfNodes.InsertElementAt(*aIndex, *node);
       (*aIndex)++;
     }
   }
 }
 
-///////////////////////////////////////////////////////////////////////////
-// ExpandSelectionForDeletion: this promotes our selection to include blocks
-// that have all their children selected.
-//
+/**
+ * Promotes selection to include blocks that have all their children selected.
+ */
 nsresult
-nsHTMLEditRules::ExpandSelectionForDeletion(Selection* aSelection)
-{
-  NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
-
-  // don't need to touch collapsed selections
-  if (aSelection->Collapsed()) {
+nsHTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
+{
+  // Don't need to touch collapsed selections
+  if (aSelection.Collapsed()) {
+    return NS_OK;
+  }
+
+  // We don't need to mess with cell selections, and we assume multirange
+  // selections are those.
+  if (aSelection.RangeCount() != 1) {
     return NS_OK;
   }
 
-  int32_t rangeCount;
-  nsresult res = aSelection->GetRangeCount(&rangeCount);
-  NS_ENSURE_SUCCESS(res, res);
-
-  // we don't need to mess with cell selections, and we assume multirange selections are those.
-  if (rangeCount != 1) return NS_OK;
-
-  // find current sel start and end
-  RefPtr<nsRange> range = aSelection->GetRangeAt(0);
-  NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
-  nsCOMPtr<nsIDOMNode> selStartNode, selEndNode, selCommon;
-  int32_t selStartOffset, selEndOffset;
-
-  res = range->GetStartContainer(getter_AddRefs(selStartNode));
-  NS_ENSURE_SUCCESS(res, res);
-  res = range->GetStartOffset(&selStartOffset);
-  NS_ENSURE_SUCCESS(res, res);
-  res = range->GetEndContainer(getter_AddRefs(selEndNode));
-  NS_ENSURE_SUCCESS(res, res);
-  res = range->GetEndOffset(&selEndOffset);
-  NS_ENSURE_SUCCESS(res, res);
-
-  // find current selection common block parent
-  res = range->GetCommonAncestorContainer(getter_AddRefs(selCommon));
-  NS_ENSURE_SUCCESS(res, res);
-  if (!IsBlockNode(selCommon))
-    selCommon = nsHTMLEditor::GetBlockNodeParent(selCommon);
+  // Find current sel start and end
+  NS_ENSURE_TRUE(aSelection.GetRangeAt(0), NS_ERROR_NULL_POINTER);
+  OwningNonNull<nsRange> range = *aSelection.GetRangeAt(0);
+
+  nsCOMPtr<nsINode> selStartNode = range->GetStartParent();
+  int32_t selStartOffset = range->StartOffset();
+  nsCOMPtr<nsINode> selEndNode = range->GetEndParent();
+  int32_t selEndOffset = range->EndOffset();
+
+  // Find current selection common block parent
+  nsCOMPtr<Element> selCommon =
+    nsHTMLEditor::GetBlock(*range->GetCommonAncestor());
   NS_ENSURE_STATE(selCommon);
 
-  // set up for loops and cache our root element
-  bool stillLooking = true;
-  nsCOMPtr<nsIDOMNode> firstBRParent;
+  // Set up for loops and cache our root element
+  nsCOMPtr<nsINode> firstBRParent;
   nsCOMPtr<nsINode> unused;
-  int32_t visOffset=0, firstBROffset=0;
+  int32_t visOffset = 0, firstBROffset = 0;
   WSType wsType;
-  nsCOMPtr<nsIContent> rootContent = mHTMLEditor->GetActiveEditingHost();
-  nsCOMPtr<nsIDOMNode> rootElement = do_QueryInterface(rootContent);
-  NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
-
-  // find previous visible thingy before start of selection
-  if ((selStartNode!=selCommon) && (selStartNode!=rootElement))
-  {
-    while (stillLooking)
-    {
+  nsCOMPtr<Element> root = mHTMLEditor->GetActiveEditingHost();
+  NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
+
+  // Find previous visible thingy before start of selection
+  if (selStartNode != selCommon && selStartNode != root) {
+    while (true) {
       nsWSRunObject wsObj(mHTMLEditor, selStartNode, selStartOffset);
-      nsCOMPtr<nsINode> selStartNode_(do_QueryInterface(selStartNode));
-      wsObj.PriorVisibleNode(selStartNode_, selStartOffset, address_of(unused),
+      wsObj.PriorVisibleNode(selStartNode, selStartOffset, address_of(unused),
                              &visOffset, &wsType);
-      if (wsType == WSType::thisBlock) {
-        // we want to keep looking up.  But stop if we are crossing table element
-        // boundaries, or if we hit the root.
-        if (nsHTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) ||
-            selCommon == GetAsDOMNode(wsObj.mStartReasonNode) ||
-            rootElement == GetAsDOMNode(wsObj.mStartReasonNode)) {
-          stillLooking = false;
-        }
-        else
-        {
-          selStartNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mStartReasonNode),
-                                                   &selStartOffset);
-        }
-      }
-      else
-      {
-        stillLooking = false;
-      }
-    }
-  }
-
-  stillLooking = true;
-  // find next visible thingy after end of selection
-  if ((selEndNode!=selCommon) && (selEndNode!=rootElement))
-  {
-    while (stillLooking)
-    {
+      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 (nsHTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) ||
+          selCommon == wsObj.mStartReasonNode ||
+          root == wsObj.mStartReasonNode) {
+        break;
+      }
+      selStartNode = wsObj.mStartReasonNode->GetParentNode();
+      selStartOffset = selStartNode ?
+        selStartNode->IndexOf(wsObj.mStartReasonNode) : -1;
+    }
+  }
+
+  // Find next visible thingy after end of selection
+  if (selEndNode != selCommon && selEndNode != root) {
+    while (true) {
       nsWSRunObject wsObj(mHTMLEditor, selEndNode, selEndOffset);
-      nsCOMPtr<nsINode> selEndNode_(do_QueryInterface(selEndNode));
-      wsObj.NextVisibleNode(selEndNode_, selEndOffset, address_of(unused),
+      wsObj.NextVisibleNode(selEndNode, selEndOffset, address_of(unused),
                             &visOffset, &wsType);
       if (wsType == WSType::br) {
-        if (mHTMLEditor->IsVisBreak(wsObj.mEndReasonNode))
-        {
-          stillLooking = false;
+        if (mHTMLEditor->IsVisBreak(wsObj.mEndReasonNode)) {
+          break;
+        }
+        if (!firstBRParent) {
+          firstBRParent = selEndNode;
+          firstBROffset = selEndOffset;
         }
-        else
-        {
-          if (!firstBRParent)
-          {
-            firstBRParent = selEndNode;
-            firstBROffset = selEndOffset;
-          }
-          selEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mEndReasonNode), &selEndOffset);
-          ++selEndOffset;
-        }
+        selEndNode = wsObj.mEndReasonNode->GetParentNode();
+        selEndOffset = selEndNode
+          ? selEndNode->IndexOf(wsObj.mEndReasonNode) + 1 : 0;
       } else if (wsType == WSType::thisBlock) {
-        // we want to keep looking up.  But stop if we are crossing table element
-        // boundaries, or if we hit the root.
+        // We want to keep looking up.  But stop if we are crossing table
+        // element boundaries, or if we hit the root.
         if (nsHTMLEditUtils::IsTableElement(wsObj.mEndReasonNode) ||
-            selCommon == GetAsDOMNode(wsObj.mEndReasonNode) ||
-            rootElement == GetAsDOMNode(wsObj.mEndReasonNode)) {
-          stillLooking = false;
-        }
-        else
-        {
-          selEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mEndReasonNode), &selEndOffset);
-          ++selEndOffset;
+            selCommon == wsObj.mEndReasonNode ||
+            root == wsObj.mEndReasonNode) {
+          break;
         }
-       }
-      else
-      {
-        stillLooking = false;
-      }
-    }
-  }
-  // now set the selection to the new range
-  aSelection->Collapse(selStartNode, selStartOffset);
-
-  // expand selection endpoint only if we didnt pass a br,
-  // or if we really needed to pass that br (ie, its block is now
-  // totally selected)
+        selEndNode = wsObj.mEndReasonNode->GetParentNode();
+        selEndOffset = 1 + selEndNode->IndexOf(wsObj.mEndReasonNode);
+      } else {
+        break;
+      }
+    }
+  }
+  // Now set the selection to the new range
+  aSelection.Collapse(selStartNode, selStartOffset);
+
+  // Expand selection endpoint only if we didn't pass a br, or if we really
+  // needed to pass that br (i.e., its block is now totally selected)
+  nsresult res;
   bool doEndExpansion = true;
-  if (firstBRParent)
-  {
-    // find block node containing br
-    nsCOMPtr<nsIDOMNode> brBlock = firstBRParent;
-    if (!IsBlockNode(brBlock))
-      brBlock = nsHTMLEditor::GetBlockNodeParent(brBlock);
-    bool nodeBefore=false, nodeAfter=false;
-
-    // create a range that represents expanded selection
-    nsCOMPtr<nsINode> node = do_QueryInterface(selStartNode);
-    NS_ENSURE_STATE(node);
-    RefPtr<nsRange> range = new nsRange(node);
+  if (firstBRParent) {
+    // Find block node containing br
+    nsCOMPtr<Element> brBlock = nsHTMLEditor::GetBlock(*firstBRParent);
+    bool nodeBefore = false, nodeAfter = false;
+
+    // Create a range that represents expanded selection
+    RefPtr<nsRange> range = new nsRange(selStartNode);
     res = range->SetStart(selStartNode, selStartOffset);
     NS_ENSURE_SUCCESS(res, res);
     res = range->SetEnd(selEndNode, selEndOffset);
     NS_ENSURE_SUCCESS(res, res);
 
-    // check if block is entirely inside range
-    nsCOMPtr<nsIContent> brContentBlock = do_QueryInterface(brBlock);
-    if (brContentBlock) {
-      res = nsRange::CompareNodeToRange(brContentBlock, range, &nodeBefore,
-                                        &nodeAfter);
-    }
-
-    // if block isn't contained, forgo grabbing the br in the expanded selection
-    if (nodeBefore || nodeAfter)
+    // Check if block is entirely inside range
+    if (brBlock) {
+      nsRange::CompareNodeToRange(brBlock, range, &nodeBefore, &nodeAfter);
+    }
+
+    // If block isn't contained, forgo grabbing the br in expanded selection
+    if (nodeBefore || nodeAfter) {
       doEndExpansion = false;
-  }
-  if (doEndExpansion)
-  {
-    res = aSelection->Extend(selEndNode, selEndOffset);
-  }
-  else
-  {
-    // only expand to just before br
-    res = aSelection->Extend(firstBRParent, firstBROffset);
-  }
-
-  return res;
+    }
+  }
+  if (doEndExpansion) {
+    res = aSelection.Extend(selEndNode, selEndOffset);
+    NS_ENSURE_SUCCESS(res, res);
+  } else {
+    // Only expand to just before br
+    res = aSelection.Extend(firstBRParent, firstBROffset);
+    NS_ENSURE_SUCCESS(res, res);
+  }
+
+  return NS_OK;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // NormalizeSelection:  tweak non-collapsed selections to be more "natural".
 //    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
@@ -5512,18 +5289,18 @@ nsHTMLEditRules::GetPromotedPoint(RulesE
 
     // look back through any further inline nodes that aren't across a <br>
     // from us, and that are enclosed in the same block.
     NS_ENSURE_TRUE(mHTMLEditor, /* void */);
     nsCOMPtr<nsINode> priorNode =
       mHTMLEditor->GetPriorHTMLNode(node, offset, true);
 
     while (priorNode && priorNode->GetParentNode() &&
-           mHTMLEditor && !mHTMLEditor->IsVisBreak(priorNode->AsDOMNode()) &&
-           !IsBlockNode(priorNode->AsDOMNode())) {
+           mHTMLEditor && !mHTMLEditor->IsVisBreak(priorNode) &&
+           !IsBlockNode(*priorNode)) {
       offset = priorNode->GetParentNode()->IndexOf(priorNode);
       node = priorNode->GetParentNode();
       NS_ENSURE_TRUE(mHTMLEditor, /* void */);
       priorNode = mHTMLEditor->GetPriorHTMLNode(node, offset, true);
     }
 
     // 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
@@ -5584,22 +5361,21 @@ nsHTMLEditRules::GetPromotedPoint(RulesE
   }
 
   // look ahead through any further inline nodes that aren't across a <br> from
   // us, and that are enclosed in the same block.
   NS_ENSURE_TRUE(mHTMLEditor, /* void */);
   nsCOMPtr<nsIContent> nextNode =
     mHTMLEditor->GetNextHTMLNode(node, offset, true);
 
-  while (nextNode && !IsBlockNode(nextNode->AsDOMNode()) &&
-         nextNode->GetParentNode()) {
+  while (nextNode && !IsBlockNode(*nextNode) && nextNode->GetParentNode()) {
     offset = 1 + nextNode->GetParentNode()->IndexOf(nextNode);
     node = nextNode->GetParentNode();
     NS_ENSURE_TRUE(mHTMLEditor, /* void */);
-    if (mHTMLEditor->IsVisBreak(nextNode->AsDOMNode())) {
+    if (mHTMLEditor->IsVisBreak(nextNode)) {
       break;
     }
 
     // Check for newlines in pre-formatted text nodes.
     bool isPRE;
     mHTMLEditor->IsPreformatted(nextNode->AsDOMNode(), &isPRE);
     if (isPRE) {
       nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(nextNode);
@@ -5901,19 +5677,18 @@ nsHTMLEditRules::GetNodesForOperation(ns
   if (aOperationType == EditAction::makeBasicBlock ||
       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(GetAsDOMNode(node)) && mHTMLEditor->IsContainer(node) &&
-          !mHTMLEditor->IsTextNode(node)) {
+      if (aTouchContent == TouchContent::yes && IsInlineNode(node) &&
+          mHTMLEditor->IsContainer(node) && !mHTMLEditor->IsTextNode(node)) {
         nsTArray<OwningNonNull<nsINode>> arrayOfInlines;
         res = BustUpInlinesAtBRs(*node->AsContent(), arrayOfInlines);
         NS_ENSURE_SUCCESS(res, res);
 
         // Put these nodes in aOutArrayOfNodes, replacing the current node
         aOutArrayOfNodes.RemoveElementAt(i);
         aOutArrayOfNodes.InsertElementsAt(i, arrayOfInlines);
       }
@@ -6119,18 +5894,17 @@ nsHTMLEditRules::GetParagraphFormatNodes
 ///////////////////////////////////////////////////////////////////////////
 // BustUpInlinesAtRangeEndpoints:
 //
 nsresult
 nsHTMLEditRules::BustUpInlinesAtRangeEndpoints(nsRangeStore &item)
 {
   bool isCollapsed = ((item.startNode == item.endNode) && (item.startOffset == item.endOffset));
 
-  nsCOMPtr<nsIContent> endInline =
-    do_QueryInterface(GetHighestInlineParent(GetAsDOMNode(item.endNode)));
+  nsCOMPtr<nsIContent> endInline = GetHighestInlineParent(*item.endNode);
 
   // if we have inline parents above range endpoints, split them
   if (endInline && !isCollapsed)
   {
     nsCOMPtr<nsINode> resultEndNode = endInline->GetParentNode();
     NS_ENSURE_STATE(mHTMLEditor);
     // item.endNode must be content if endInline isn't null
     int32_t resultEndOffset =
@@ -6138,18 +5912,17 @@ nsHTMLEditRules::BustUpInlinesAtRangeEnd
                                  item.endOffset,
                                  nsEditor::EmptyContainers::no);
     NS_ENSURE_TRUE(resultEndOffset != -1, NS_ERROR_FAILURE);
     // reset range
     item.endNode = resultEndNode;
     item.endOffset = resultEndOffset;
   }
 
-  nsCOMPtr<nsIContent> startInline =
-    do_QueryInterface(GetHighestInlineParent(GetAsDOMNode(item.startNode)));
+  nsCOMPtr<nsIContent> startInline = GetHighestInlineParent(*item.startNode);
 
   if (startInline)
   {
     nsCOMPtr<nsINode> resultStartNode = startInline->GetParentNode();
     NS_ENSURE_STATE(mHTMLEditor);
     int32_t resultStartOffset =
       mHTMLEditor->SplitNodeDeep(*startInline, *item.startNode->AsContent(),
                                  item.startOffset,
@@ -6222,29 +5995,28 @@ nsHTMLEditRules::BustUpInlinesAtBRs(nsIC
   // Now tack on remaining rightNode, if any, to the list
   if (rightNode) {
     aOutArrayOfNodes.AppendElement(*rightNode);
   }
   return NS_OK;
 }
 
 
-nsCOMPtr<nsIDOMNode>
-nsHTMLEditRules::GetHighestInlineParent(nsIDOMNode* aNode)
-{
-  NS_ENSURE_TRUE(aNode, nullptr);
-  if (IsBlockNode(aNode)) return nullptr;
-  nsCOMPtr<nsIDOMNode> inlineNode, node=aNode;
-
-  while (node && IsInlineNode(node))
-  {
-    inlineNode = node;
-    inlineNode->GetParentNode(getter_AddRefs(node));
-  }
-  return inlineNode;
+nsIContent*
+nsHTMLEditRules::GetHighestInlineParent(nsINode& aNode)
+{
+  if (!aNode.IsContent() || IsBlockNode(aNode)) {
+    return nullptr;
+  }
+  OwningNonNull<nsIContent> node = *aNode.AsContent();
+
+  while (node->GetParent() && IsInlineNode(*node->GetParent())) {
+    node = *node->GetParent();
+  }
+  return node;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // GetNodesFromPoint: Given a particular operation, construct a list of nodes
 //                    from a point that will be operated on.
 //
 nsresult
@@ -6349,170 +6121,155 @@ nsHTMLEditRules::IsInListItem(nsINode* a
       return parent;
     }
     parent = parent->GetParentElement();
   }
   return nullptr;
 }
 
 
-///////////////////////////////////////////////////////////////////////////
-// ReturnInHeader: do the right thing for returns pressed in headers
-//
+/**
+ * ReturnInHeader: do the right thing for returns pressed in headers
+ */
 nsresult
-nsHTMLEditRules::ReturnInHeader(Selection* aSelection,
-                                nsIDOMNode *aHeader,
-                                nsIDOMNode *aNode,
+nsHTMLEditRules::ReturnInHeader(Selection& aSelection,
+                                Element& aHeader,
+                                nsINode& aNode,
                                 int32_t aOffset)
 {
-  nsCOMPtr<Element> header = do_QueryInterface(aHeader);
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  NS_ENSURE_TRUE(aSelection && header && node, NS_ERROR_NULL_POINTER);
-
-  // remeber where the header is
-  int32_t offset;
-  nsCOMPtr<nsIDOMNode> headerParent = nsEditor::GetNodeLocation(aHeader, &offset);
-
-  // get ws code to adjust any ws
   NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  // Remember where the header is
+  nsCOMPtr<nsINode> headerParent = aHeader.GetParentNode();
+  int32_t offset = headerParent ? headerParent->IndexOf(&aHeader) : -1;
+
+  // Get ws code to adjust any ws
+  nsCOMPtr<nsINode> node = &aNode;
   nsresult res = nsWSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor,
                                                            address_of(node),
                                                            &aOffset);
   NS_ENSURE_SUCCESS(res, res);
 
-  // split the header
+  // Split the header
   NS_ENSURE_STATE(node->IsContent());
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->SplitNodeDeep(*header, *node->AsContent(), aOffset);
-
-  // if the leftand heading is empty, put a mozbr in it
-  nsCOMPtr<nsIDOMNode> prevItem;
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->GetPriorHTMLSibling(aHeader, address_of(prevItem));
-  if (prevItem && nsHTMLEditUtils::IsHeader(prevItem))
-  {
-    bool bIsEmptyNode;
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->IsEmptyNode(prevItem, &bIsEmptyNode);
+  mHTMLEditor->SplitNodeDeep(aHeader, *node->AsContent(), aOffset);
+
+  // If the left-hand heading is empty, put a mozbr in it
+  nsCOMPtr<nsIContent> prevItem = mHTMLEditor->GetPriorHTMLSibling(&aHeader);
+  if (prevItem && nsHTMLEditUtils::IsHeader(*prevItem)) {
+    bool isEmptyNode;
+    res = mHTMLEditor->IsEmptyNode(prevItem, &isEmptyNode);
     NS_ENSURE_SUCCESS(res, res);
-    if (bIsEmptyNode) {
-      res = CreateMozBR(prevItem, 0);
+    if (isEmptyNode) {
+      res = CreateMozBR(prevItem->AsDOMNode(), 0);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
 
-  // if the new (righthand) header node is empty, delete it
+  // If the new (righthand) header node is empty, delete it
   bool isEmpty;
-  res = IsEmptyBlock(aHeader, &isEmpty, true);
+  res = IsEmptyBlock(aHeader, &isEmpty, MozBRCounts::no);
   NS_ENSURE_SUCCESS(res, res);
-  if (isEmpty)
-  {
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->DeleteNode(aHeader);
-    NS_ENSURE_SUCCESS(res, res);
-    // layout tells the caret to blink in a weird place
-    // if we don't place a break after the header.
-    nsCOMPtr<nsIDOMNode> sibling;
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetNextHTMLSibling(headerParent, offset+1, address_of(sibling));
+  if (isEmpty) {
+    res = mHTMLEditor->DeleteNode(&aHeader);
     NS_ENSURE_SUCCESS(res, res);
-    if (!sibling || !nsTextEditUtils::IsBreak(sibling))
-    {
+    // Layout tells the caret to blink in a weird place if we don't place a
+    // break after the header.
+    nsCOMPtr<nsIContent> sibling =
+      mHTMLEditor->GetNextHTMLSibling(headerParent, offset + 1);
+    if (!sibling || !sibling->IsHTMLElement(nsGkAtoms::br)) {
       ClearCachedStyles();
-      NS_ENSURE_STATE(mHTMLEditor);
       mHTMLEditor->mTypeInState->ClearAllProps();
 
-      // create a paragraph
-      NS_NAMED_LITERAL_STRING(pType, "p");
-      nsCOMPtr<nsIDOMNode> pNode;
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->CreateNode(pType, headerParent, offset+1, getter_AddRefs(pNode));
-      NS_ENSURE_SUCCESS(res, res);
-
-      // append a <br> to it
-      nsCOMPtr<nsIDOMNode> brNode;
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->CreateBR(pNode, 0, address_of(brNode));
+      // Create a paragraph
+      nsCOMPtr<Element> pNode =
+        mHTMLEditor->CreateNode(nsGkAtoms::p, headerParent, offset + 1);
+      NS_ENSURE_STATE(pNode);
+
+      // Append a <br> to it
+      nsCOMPtr<Element> brNode = mHTMLEditor->CreateBR(pNode, 0);
+      NS_ENSURE_STATE(brNode);
+
+      // Set selection to before the break
+      res = aSelection.Collapse(pNode, 0);
       NS_ENSURE_SUCCESS(res, res);
-
-      // set selection to before the break
-      res = aSelection->Collapse(pNode, 0);
-    }
-    else
-    {
-      headerParent = nsEditor::GetNodeLocation(sibling, &offset);
-      // put selection after break
-      res = aSelection->Collapse(headerParent,offset+1);
-    }
-  }
-  else
-  {
-    // put selection at front of righthand heading
-    res = aSelection->Collapse(aHeader,0);
-  }
-  return res;
+    } else {
+      headerParent = sibling->GetParentNode();
+      offset = headerParent ? headerParent->IndexOf(sibling) : -1;
+      // Put selection after break
+      res = aSelection.Collapse(headerParent, offset + 1);
+      NS_ENSURE_SUCCESS(res, res);
+    }
+  } else {
+    // Put selection at front of righthand heading
+    res = aSelection.Collapse(&aHeader, 0);
+    NS_ENSURE_SUCCESS(res, res);
+  }
+  return NS_OK;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // ReturnInParagraph: do the right thing for returns pressed in paragraphs
 //
 nsresult
 nsHTMLEditRules::ReturnInParagraph(Selection* aSelection,
                                    nsIDOMNode* aPara,
                                    nsIDOMNode* aNode,
                                    int32_t aOffset,
                                    bool* aCancel,
                                    bool* aHandled)
 {
-  if (!aSelection || !aPara || !aNode || !aCancel || !aHandled) {
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+  if (!aSelection || !aPara || !node || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
   *aCancel = false;
   *aHandled = false;
   nsresult res;
 
   int32_t offset;
-  nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(aNode, &offset);
+  nsCOMPtr<nsINode> parent = nsEditor::GetNodeLocation(node, &offset);
 
   NS_ENSURE_STATE(mHTMLEditor);
   bool doesCRCreateNewP = mHTMLEditor->GetReturnInParagraphCreatesNewParagraph();
 
   bool newBRneeded = false;
   bool newSelNode = false;
-  nsCOMPtr<nsIDOMNode> sibling;
+  nsCOMPtr<nsIContent> sibling;
   nsCOMPtr<nsIDOMNode> selNode = aNode;
   int32_t selOffset = aOffset;
 
   NS_ENSURE_STATE(mHTMLEditor);
   if (aNode == aPara && doesCRCreateNewP) {
     // we are at the edges of the block, newBRneeded not needed!
-    sibling = aNode;
+    sibling = node->AsContent();
   } else if (mHTMLEditor->IsTextNode(aNode)) {
     nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(aNode);
     uint32_t strLength;
     res = textNode->GetLength(&strLength);
     NS_ENSURE_SUCCESS(res, res);
 
     // at beginning of text node?
     if (!aOffset) {
       // is there a BR prior to it?
       NS_ENSURE_STATE(mHTMLEditor);
-      mHTMLEditor->GetPriorHTMLSibling(aNode, address_of(sibling));
+      sibling = mHTMLEditor->GetPriorHTMLSibling(node);
       if (!sibling || !mHTMLEditor || !mHTMLEditor->IsVisBreak(sibling) ||
-          nsTextEditUtils::HasMozAttr(sibling)) {
+          nsTextEditUtils::HasMozAttr(GetAsDOMNode(sibling))) {
         NS_ENSURE_STATE(mHTMLEditor);
         newBRneeded = true;
       }
     } else if (aOffset == (int32_t)strLength) {
       // we're at the end of text node...
       // is there a BR after to it?
       NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->GetNextHTMLSibling(aNode, address_of(sibling));
+      sibling = mHTMLEditor->GetNextHTMLSibling(node);
       if (!sibling || !mHTMLEditor || !mHTMLEditor->IsVisBreak(sibling) ||
-          nsTextEditUtils::HasMozAttr(sibling)) {
+          nsTextEditUtils::HasMozAttr(GetAsDOMNode(sibling))) {
         NS_ENSURE_STATE(mHTMLEditor);
         newBRneeded = true;
         offset++;
       }
     } else {
       if (doesCRCreateNewP) {
         nsCOMPtr<nsIDOMNode> tmp;
         res = mEditor->SplitNode(aNode, aOffset, getter_AddRefs(tmp));
@@ -6521,64 +6278,60 @@ nsHTMLEditRules::ReturnInParagraph(Selec
       }
 
       newBRneeded = true;
       offset++;
     }
   } else {
     // not in a text node.
     // is there a BR prior to it?
-    nsCOMPtr<nsIDOMNode> nearNode;
+    nsCOMPtr<nsIContent> nearNode;
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetPriorHTMLNode(aNode, aOffset, address_of(nearNode));
-    NS_ENSURE_SUCCESS(res, res);
+    nearNode = mHTMLEditor->GetPriorHTMLNode(node, aOffset);
     NS_ENSURE_STATE(mHTMLEditor);
     if (!nearNode || !mHTMLEditor->IsVisBreak(nearNode) ||
-        nsTextEditUtils::HasMozAttr(nearNode)) {
+        nsTextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) {
       // is there a BR after it?
       NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->GetNextHTMLNode(aNode, aOffset, address_of(nearNode));
-      NS_ENSURE_SUCCESS(res, res);
+      nearNode = mHTMLEditor->GetNextHTMLNode(node, aOffset);
       NS_ENSURE_STATE(mHTMLEditor);
       if (!nearNode || !mHTMLEditor->IsVisBreak(nearNode) ||
-          nsTextEditUtils::HasMozAttr(nearNode)) {
+          nsTextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) {
         newBRneeded = true;
-        parent = aNode;
+        parent = node;
         offset = aOffset;
         newSelNode = true;
       }
     }
     if (!newBRneeded) {
       sibling = nearNode;
     }
   }
   if (newBRneeded) {
     // if CR does not create a new P, default to BR creation
     NS_ENSURE_TRUE(doesCRCreateNewP, NS_OK);
 
-    nsCOMPtr<nsIDOMNode> brNode;
     NS_ENSURE_STATE(mHTMLEditor);
-    res =  mHTMLEditor->CreateBR(parent, offset, address_of(brNode));
-    sibling = brNode;
+    sibling = mHTMLEditor->CreateBR(parent, offset);
     if (newSelNode) {
       // We split the parent after the br we've just inserted.
-      selNode = parent;
+      selNode = GetAsDOMNode(parent);
       selOffset = offset + 1;
     }
   }
   *aHandled = true;
   return SplitParagraph(aPara, sibling, aSelection, address_of(selNode), &selOffset);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // SplitParagraph: split a paragraph at selection point, possibly deleting a br
 //
 nsresult
 nsHTMLEditRules::SplitParagraph(nsIDOMNode *aPara,
-                                nsIDOMNode *aBRNode,
+                                nsIContent* aBRNode,
                                 Selection* aSelection,
                                 nsCOMPtr<nsIDOMNode> *aSelNode,
                                 int32_t *aOffset)
 {
   nsCOMPtr<Element> para = do_QueryInterface(aPara);
   NS_ENSURE_TRUE(para && aBRNode && aSelNode && *aSelNode && aOffset &&
                  aSelection, NS_ERROR_NULL_POINTER);
   nsresult res = NS_OK;
@@ -6609,19 +6362,19 @@ nsHTMLEditRules::SplitParagraph(nsIDOMNo
 
   // remove ID attribute on the paragraph we just created
   nsCOMPtr<nsIDOMElement> rightElt = do_QueryInterface(rightPara);
   NS_ENSURE_STATE(mHTMLEditor);
   res = mHTMLEditor->RemoveAttribute(rightElt, NS_LITERAL_STRING("id"));
   NS_ENSURE_SUCCESS(res, res);
 
   // check both halves of para to see if we need mozBR
-  res = InsertMozBRIfNeeded(GetAsDOMNode(leftPara));
+  res = InsertMozBRIfNeeded(*leftPara);
   NS_ENSURE_SUCCESS(res, res);
-  res = InsertMozBRIfNeeded(GetAsDOMNode(rightPara));
+  res = InsertMozBRIfNeeded(*rightPara);
   NS_ENSURE_SUCCESS(res, res);
 
   // selection to beginning of right hand para;
   // look inside any containers that are up front.
   nsCOMPtr<nsINode> rightParaNode = do_QueryInterface(rightPara);
   NS_ENSURE_STATE(mHTMLEditor && rightParaNode);
   nsCOMPtr<nsIDOMNode> child =
     GetAsDOMNode(mHTMLEditor->GetLeftmostChild(rightParaNode, true));
@@ -6635,188 +6388,170 @@ nsHTMLEditRules::SplitParagraph(nsIDOMNo
     int32_t offset;
     nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(child, &offset);
     aSelection->Collapse(parent,offset);
   }
   return res;
 }
 
 
-///////////////////////////////////////////////////////////////////////////
-// ReturnInListItem: do the right thing for returns pressed in list items
-//
+/**
+ * ReturnInListItem: do the right thing for returns pressed in list items
+ */
 nsresult
-nsHTMLEditRules::ReturnInListItem(Selection* aSelection,
-                                  nsIDOMNode *aListItem,
-                                  nsIDOMNode *aNode,
+nsHTMLEditRules::ReturnInListItem(Selection& aSelection,
+                                  Element& aListItem,
+                                  nsINode& aNode,
                                   int32_t aOffset)
 {
-  nsCOMPtr<Element> listItem = do_QueryInterface(aListItem);
-  NS_ENSURE_TRUE(aSelection && listItem && aNode, NS_ERROR_NULL_POINTER);
-  nsresult res = NS_OK;
-
-  nsCOMPtr<nsIDOMNode> listitem;
-
-  // sanity check
-  NS_PRECONDITION(true == nsHTMLEditUtils::IsListItem(aListItem),
-                  "expected a list item and didn't get one");
-
-  // get the listitem parent and the active editing host.
+  MOZ_ASSERT(nsHTMLEditUtils::IsListItem(&aListItem));
+
   NS_ENSURE_STATE(mHTMLEditor);
-  nsIContent* rootContent = mHTMLEditor->GetActiveEditingHost();
-  nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(rootContent);
-  nsCOMPtr<nsINode> list = listItem->GetParentNode();
-  int32_t itemOffset = list ? list->IndexOf(listItem) : -1;
-
-  // if we are in an empty listitem, then we want to pop up out of the list
-  // but only if prefs says it's ok and if the parent isn't the active editing host.
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  // Get the item parent and the active editing host.
+  nsCOMPtr<Element> root = mHTMLEditor->GetActiveEditingHost();
+
+  nsCOMPtr<Element> list = aListItem.GetParentElement();
+  int32_t itemOffset = list ? list->IndexOf(&aListItem) : -1;
+
+  // 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.
   bool isEmpty;
-  res = IsEmptyBlock(aListItem, &isEmpty, true, false);
+  nsresult res = IsEmptyBlock(aListItem, &isEmpty, MozBRCounts::no);
   NS_ENSURE_SUCCESS(res, res);
-  if (isEmpty && (rootNode != GetAsDOMNode(list)) &&
-      mReturnInEmptyLIKillsList) {
-    // get the list offset now -- before we might eventually split the list
+  if (isEmpty && root != list && mReturnInEmptyLIKillsList) {
+    // Get the list offset now -- before we might eventually split the list
     nsCOMPtr<nsINode> listParent = list->GetParentNode();
     int32_t offset = listParent ? listParent->IndexOf(list) : -1;
 
-    // are we the last list item in the list?
-    bool bIsLast;
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->IsLastEditableChild(aListItem, &bIsLast);
+    // Are we the last list item in the list?
+    bool isLast;
+    res = mHTMLEditor->IsLastEditableChild(aListItem.AsDOMNode(), &isLast);
     NS_ENSURE_SUCCESS(res, res);
-    if (!bIsLast)
-    {
-      // we need to split the list!
-      nsCOMPtr<nsIDOMNode> tempNode;
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->SplitNode(GetAsDOMNode(list), itemOffset,
-                                   getter_AddRefs(tempNode));
-      NS_ENSURE_SUCCESS(res, res);
-    }
-
-    // are we in a sublist?
+    if (!isLast) {
+      // We need to split the list!
+      ErrorResult rv;
+      mHTMLEditor->SplitNode(*list, itemOffset, rv);
+      NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
+    }
+
+    // Are we in a sublist?
     if (nsHTMLEditUtils::IsList(listParent)) {
-      // if so, move this list item out of this list and into the grandparent list
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->MoveNode(listItem, listParent, offset + 1);
+      // If so, move item out of this list and into the grandparent list
+      res = mHTMLEditor->MoveNode(&aListItem, listParent, offset + 1);
       NS_ENSURE_SUCCESS(res, res);
-      res = aSelection->Collapse(aListItem,0);
-    }
-    else
-    {
-      // otherwise kill this listitem
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->DeleteNode(aListItem);
+      res = aSelection.Collapse(&aListItem, 0);
       NS_ENSURE_SUCCESS(res, res);
-
-      // time to insert a paragraph
-      NS_NAMED_LITERAL_STRING(pType, "p");
-      nsCOMPtr<nsIDOMNode> pNode;
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->CreateNode(pType, GetAsDOMNode(listParent),
-                                    offset + 1, getter_AddRefs(pNode));
+    } else {
+      // Otherwise kill this item
+      res = mHTMLEditor->DeleteNode(&aListItem);
       NS_ENSURE_SUCCESS(res, res);
 
-      // append a <br> to it
-      nsCOMPtr<nsIDOMNode> brNode;
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->CreateBR(pNode, 0, address_of(brNode));
+      // Time to insert a paragraph
+      nsCOMPtr<Element> pNode =
+        mHTMLEditor->CreateNode(nsGkAtoms::p, listParent, offset + 1);
+      NS_ENSURE_STATE(pNode);
+
+      // Append a <br> to it
+      nsCOMPtr<Element> brNode = mHTMLEditor->CreateBR(pNode, 0);
+      NS_ENSURE_STATE(brNode);
+
+      // Set selection to before the break
+      res = aSelection.Collapse(pNode, 0);
       NS_ENSURE_SUCCESS(res, res);
-
-      // set selection to before the break
-      res = aSelection->Collapse(pNode, 0);
-    }
-    return res;
-  }
-
-  // else we want a new list item at the same list level.
-  // get ws code to adjust any ws
-  nsCOMPtr<nsINode> selNode(do_QueryInterface(aNode));
-  NS_ENSURE_STATE(mHTMLEditor);
-  res = nsWSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor, address_of(selNode), &aOffset);
+    }
+    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;
+  res = nsWSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor,
+                                                  address_of(selNode),
+                                                  &aOffset);
   NS_ENSURE_SUCCESS(res, res);
-  // now split list item
-  NS_ENSURE_STATE(mHTMLEditor);
+  // Now split list item
   NS_ENSURE_STATE(selNode->IsContent());
-  mHTMLEditor->SplitNodeDeep(*listItem, *selNode->AsContent(), aOffset);
-  // 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<nsIDOMNode> prevItem;
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->GetPriorHTMLSibling(aListItem, address_of(prevItem));
-
-  if (prevItem && nsHTMLEditUtils::IsListItem(prevItem))
-  {
-    bool bIsEmptyNode;
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->IsEmptyNode(prevItem, &bIsEmptyNode);
+  mHTMLEditor->SplitNodeDeep(aListItem, *selNode->AsContent(), aOffset);
+
+  // 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 = mHTMLEditor->GetPriorHTMLSibling(&aListItem);
+  if (prevItem && nsHTMLEditUtils::IsListItem(prevItem)) {
+    bool isEmptyNode;
+    res = mHTMLEditor->IsEmptyNode(prevItem, &isEmptyNode);
     NS_ENSURE_SUCCESS(res, res);
-    if (bIsEmptyNode) {
-      res = CreateMozBR(prevItem, 0);
+    if (isEmptyNode) {
+      res = CreateMozBR(prevItem->AsDOMNode(), 0);
       NS_ENSURE_SUCCESS(res, res);
     } else {
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->IsEmptyNode(aListItem, &bIsEmptyNode, true);
+      res = mHTMLEditor->IsEmptyNode(&aListItem, &isEmptyNode, true);
       NS_ENSURE_SUCCESS(res, res);
-      if (bIsEmptyNode)
-      {
-        nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aListItem);
+      if (isEmptyNode) {
+        nsCOMPtr<nsIAtom> nodeAtom = aListItem.NodeInfo()->NameAtom();
         if (nodeAtom == nsGkAtoms::dd || nodeAtom == nsGkAtoms::dt) {
-          int32_t itemOffset;
-          nsCOMPtr<nsIDOMNode> list = nsEditor::GetNodeLocation(aListItem, &itemOffset);
-
-          nsAutoString listTag(nodeAtom == nsGkAtoms::dt
-            ? NS_LITERAL_STRING("dd") : NS_LITERAL_STRING("dt"));
-          nsCOMPtr<nsIDOMNode> newListItem;
-          NS_ENSURE_STATE(mHTMLEditor);
-          res = mHTMLEditor->CreateNode(listTag, list, itemOffset+1, getter_AddRefs(newListItem));
+          nsCOMPtr<nsINode> list = aListItem.GetParentNode();
+          int32_t itemOffset = list ? list->IndexOf(&aListItem) : -1;
+
+          nsIAtom* listAtom = nodeAtom == nsGkAtoms::dt ? nsGkAtoms::dd
+                                                        : nsGkAtoms::dt;
+          nsCOMPtr<Element> newListItem =
+            mHTMLEditor->CreateNode(listAtom, list, itemOffset + 1);
+          NS_ENSURE_STATE(newListItem);
+          res = mEditor->DeleteNode(&aListItem);
           NS_ENSURE_SUCCESS(res, res);
-          res = mEditor->DeleteNode(aListItem);
+          res = aSelection.Collapse(newListItem, 0);
           NS_ENSURE_SUCCESS(res, res);
-          return aSelection->Collapse(newListItem, 0);
+
+          return NS_OK;
         }
 
-        nsCOMPtr<nsIDOMNode> brNode;
-        NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->CopyLastEditableChildStyles(prevItem, aListItem, getter_AddRefs(brNode));
+        nsCOMPtr<Element> brNode;
+        res = mHTMLEditor->CopyLastEditableChildStyles(GetAsDOMNode(prevItem),
+          GetAsDOMNode(&aListItem), getter_AddRefs(brNode));
         NS_ENSURE_SUCCESS(res, res);
-        if (brNode)
-        {
-          int32_t offset;
-          nsCOMPtr<nsIDOMNode> brParent = nsEditor::GetNodeLocation(brNode, &offset);
-          return aSelection->Collapse(brParent, offset);
+        if (brNode) {
+          nsCOMPtr<nsINode> brParent = brNode->GetParentNode();
+          int32_t offset = brParent ? brParent->IndexOf(brNode) : -1;
+          res = aSelection.Collapse(brParent, offset);
+          NS_ENSURE_SUCCESS(res, res);
+
+          return NS_OK;
         }
-      }
-      else
-      {
-        NS_ENSURE_STATE(mHTMLEditor);
-        nsWSRunObject wsObj(mHTMLEditor, aListItem, 0);
-        nsCOMPtr<nsINode> visNode_;
+      } else {
+        nsWSRunObject wsObj(mHTMLEditor, &aListItem, 0);
+        nsCOMPtr<nsINode> visNode;
         int32_t visOffset = 0;
         WSType wsType;
-        nsCOMPtr<nsINode> aListItem_(do_QueryInterface(aListItem));
-        wsObj.NextVisibleNode(aListItem_, 0, address_of(visNode_),
+        wsObj.NextVisibleNode(&aListItem, 0, address_of(visNode),
                               &visOffset, &wsType);
-        nsCOMPtr<nsIDOMNode> visNode(GetAsDOMNode(visNode_));
         if (wsType == WSType::special || wsType == WSType::br ||
-            nsHTMLEditUtils::IsHR(visNode)) {
-          int32_t offset;
-          nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(visNode, &offset);
-          return aSelection->Collapse(parent, offset);
+            visNode->IsHTMLElement(nsGkAtoms::hr)) {
+          nsCOMPtr<nsINode> parent = visNode->GetParentNode();
+          int32_t offset = parent ? parent->IndexOf(visNode) : -1;
+          res = aSelection.Collapse(parent, offset);
+          NS_ENSURE_SUCCESS(res, res);
+
+          return NS_OK;
+        } else {
+          res = aSelection.Collapse(visNode, visOffset);
+          NS_ENSURE_SUCCESS(res, res);
+
+          return NS_OK;
         }
-        else
-        {
-          return aSelection->Collapse(visNode, visOffset);
-        }
-      }
-    }
-  }
-  res = aSelection->Collapse(aListItem,0);
-  return res;
+      }
+    }
+  }
+  res = aSelection.Collapse(&aListItem, 0);
+  NS_ENSURE_SUCCESS(res, res);
+
+  return NS_OK;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // MakeBlockquote: Put the list of nodes into one or more blockquotes.
 //
 nsresult
 nsHTMLEditRules::MakeBlockquote(nsTArray<OwningNonNull<nsINode>>& aNodeArray)
@@ -6863,17 +6598,17 @@ nsHTMLEditRules::MakeBlockquote(nsTArray
       int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
       res = SplitAsNeeded(*nsGkAtoms::blockquote, curParent, offset);
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_STATE(mHTMLEditor);
       curBlock = mHTMLEditor->CreateNode(nsGkAtoms::blockquote, curParent,
                                          offset);
       NS_ENSURE_STATE(curBlock);
       // remember our new block for postprocessing
-      mNewBlock = curBlock->AsDOMNode();
+      mNewBlock = curBlock;
       // note: doesn't matter if we set mNewBlock multiple times.
     }
 
     NS_ENSURE_STATE(mHTMLEditor);
     res = mHTMLEditor->MoveNode(curNode->AsContent(), curBlock, -1);
     NS_ENSURE_SUCCESS(res, res);
   }
   return NS_OK;
@@ -6900,17 +6635,17 @@ nsHTMLEditRules::RemoveBlockStyle(nsTArr
     if (nsHTMLEditUtils::IsFormatNode(curNode)) {
       // Process any partial progress saved
       if (curBlock) {
         res = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
         NS_ENSURE_SUCCESS(res, res);
         firstNode = lastNode = curBlock = nullptr;
       }
       // Remove current block
-      res = mHTMLEditor->RemoveBlockContainer(curNode->AsDOMNode());
+      res = mHTMLEditor->RemoveBlockContainer(*curNode->AsContent());
       NS_ENSURE_SUCCESS(res, res);
     } else if (curNode->IsAnyOfHTMLElements(nsGkAtoms::table,
                                             nsGkAtoms::tr,
                                             nsGkAtoms::tbody,
                                             nsGkAtoms::td,
                                             nsGkAtoms::li,
                                             nsGkAtoms::blockquote,
                                             nsGkAtoms::div) ||
@@ -6921,17 +6656,17 @@ nsHTMLEditRules::RemoveBlockStyle(nsTArr
         NS_ENSURE_SUCCESS(res, res);
         firstNode = lastNode = curBlock = nullptr;
       }
       // Recursion time
       nsTArray<OwningNonNull<nsINode>> childArray;
       GetChildNodesForOperation(*curNode, childArray);
       res = RemoveBlockStyle(childArray);
       NS_ENSURE_SUCCESS(res, res);
-    } else if (IsInlineNode(GetAsDOMNode(curNode))) {
+    } else if (IsInlineNode(curNode)) {
       if (curBlock) {
         // If so, is this node a descendant?
         if (nsEditorUtils::IsDescendantOf(curNode, curBlock)) {
           // Then we don't need to do anything different for this node
           lastNode = curNode->AsContent();
           continue;
         } else {
           // Otherwise, we have progressed beyond end of curBlock, so let's
@@ -7035,17 +6770,17 @@ nsHTMLEditRules::ApplyBlockStyle(nsTArra
       } else {
         // Make sure we can put a block here
         res = SplitAsNeeded(aBlockTag, curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
         nsCOMPtr<Element> theBlock =
           mHTMLEditor->CreateNode(&aBlockTag, curParent, offset);
         NS_ENSURE_STATE(theBlock);
         // Remember our new block for postprocessing
-        mNewBlock = theBlock->AsDOMNode();
+        mNewBlock = theBlock;
       }
     } else 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;
         res = mHTMLEditor->DeleteNode(curNode);
@@ -7053,22 +6788,22 @@ nsHTMLEditRules::ApplyBlockStyle(nsTArra
       } else {
         // The break is the first (or even only) node we encountered.  Create a
         // block for it.
         res = SplitAsNeeded(aBlockTag, curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
         curBlock = mHTMLEditor->CreateNode(&aBlockTag, curParent, offset);
         NS_ENSURE_STATE(curBlock);
         // Remember our new block for postprocessing
-        mNewBlock = curBlock->AsDOMNode();
+        mNewBlock = curBlock;
         // Note: doesn't matter if we set mNewBlock multiple times.
         res = mHTMLEditor->MoveNode(curNode->AsContent(), curBlock, -1);
         NS_ENSURE_SUCCESS(res, res);
       }
-    } else if (IsInlineNode(GetAsDOMNode(curNode))) {
+    } else 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 && !mHTMLEditor->IsEditable(curNode)) {
@@ -7078,17 +6813,17 @@ nsHTMLEditRules::ApplyBlockStyle(nsTArra
 
       // If no curBlock, make one
       if (!curBlock) {
         res = SplitAsNeeded(aBlockTag, curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
         curBlock = mHTMLEditor->CreateNode(&aBlockTag, curParent, offset);
         NS_ENSURE_STATE(curBlock);
         // Remember our new block for postprocessing
-        mNewBlock = curBlock->AsDOMNode();
+        mNewBlock = curBlock;
         // Note: doesn't matter if we set mNewBlock multiple times.
       }
 
       // 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.
       res = mHTMLEditor->MoveNode(curNode->AsContent(), curBlock, -1);
@@ -7100,16 +6835,28 @@ nsHTMLEditRules::ApplyBlockStyle(nsTArra
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // SplitAsNeeded: Given a tag name, split inOutParent up to the point where we
 //                can insert the tag.  Adjust inOutParent and inOutOffset to
 //                point to new location for tag.
 nsresult
 nsHTMLEditRules::SplitAsNeeded(nsIAtom& aTag,
+                               OwningNonNull<nsINode>& aInOutParent,
+                               int32_t& aInOutOffset)
+{
+  // XXX Is there a better way to do this?
+  nsCOMPtr<nsINode> parent = aInOutParent.forget();
+  nsresult res = SplitAsNeeded(aTag, parent, aInOutOffset);
+  aInOutParent = parent.forget();
+  return res;
+}
+
+nsresult
+nsHTMLEditRules::SplitAsNeeded(nsIAtom& aTag,
                                nsCOMPtr<nsINode>& inOutParent,
                                int32_t& inOutOffset)
 {
   NS_ENSURE_TRUE(inOutParent, NS_ERROR_NULL_POINTER);
 
   // Check that we have a place that can legally contain the tag
   nsCOMPtr<nsINode> tagParent, splitNode;
   for (nsCOMPtr<nsINode> parent = inOutParent; parent;
@@ -7402,28 +7149,28 @@ nsHTMLEditRules::PinSelectionToNewBlock(
   // use ranges and sRangeHelper to compare sel point to new block
   nsCOMPtr<nsINode> node = do_QueryInterface(selNode);
   NS_ENSURE_STATE(node);
   RefPtr<nsRange> range = new nsRange(node);
   res = range->SetStart(selNode, selOffset);
   NS_ENSURE_SUCCESS(res, res);
   res = range->SetEnd(selNode, selOffset);
   NS_ENSURE_SUCCESS(res, res);
-  nsCOMPtr<nsIContent> block (do_QueryInterface(mNewBlock));
+  nsCOMPtr<nsIContent> block = mNewBlock.get();
   NS_ENSURE_TRUE(block, NS_ERROR_NO_INTERFACE);
   bool nodeBefore, nodeAfter;
   res = nsRange::CompareNodeToRange(block, range, &nodeBefore, &nodeAfter);
   NS_ENSURE_SUCCESS(res, res);
 
   if (nodeBefore && nodeAfter)
     return NS_OK;  // selection is inside block
   else if (nodeBefore)
   {
     // selection is after block.  put at end of block.
-    nsCOMPtr<nsIDOMNode> tmp = mNewBlock;
+    nsCOMPtr<nsIDOMNode> tmp = GetAsDOMNode(mNewBlock);
     NS_ENSURE_STATE(mHTMLEditor);
     tmp = GetAsDOMNode(mHTMLEditor->GetLastEditableChild(*block));
     uint32_t endPoint;
     if (mHTMLEditor->IsTextNode(tmp) ||
         mHTMLEditor->IsContainer(tmp))
     {
       res = nsEditor::GetLengthOfDOMNode(tmp, endPoint);
       NS_ENSURE_SUCCESS(res, res);
@@ -7433,71 +7180,68 @@ nsHTMLEditRules::PinSelectionToNewBlock(
       tmp = nsEditor::GetNodeLocation(tmp, (int32_t*)&endPoint);
       endPoint++;  // want to be after this node
     }
     return aSelection->Collapse(tmp, (int32_t)endPoint);
   }
   else
   {
     // selection is before block.  put at start of block.
-    nsCOMPtr<nsIDOMNode> tmp = mNewBlock;
+    nsCOMPtr<nsIDOMNode> tmp = GetAsDOMNode(mNewBlock);
+    NS_ENSURE_STATE(mHTMLEditor);
     tmp = GetAsDOMNode(mHTMLEditor->GetFirstEditableChild(*block));
     int32_t offset;
     if (mHTMLEditor->IsTextNode(tmp) ||
         mHTMLEditor->IsContainer(tmp))
     {
       tmp = nsEditor::GetNodeLocation(tmp, &offset);
     }
     return aSelection->Collapse(tmp, 0);
   }
 }
 
-nsresult
-nsHTMLEditRules::CheckInterlinePosition(Selection* aSelection)
-{
-  NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
-
-  // if the selection isn't collapsed, do nothing.
-  if (!aSelection->Collapsed()) {
-    return NS_OK;
-  }
-
-  // get the (collapsed) selection location
-  nsCOMPtr<nsIDOMNode> selNode, node;
-  int32_t selOffset;
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsresult res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(selNode), &selOffset);
-  NS_ENSURE_SUCCESS(res, res);
+void
+nsHTMLEditRules::CheckInterlinePosition(Selection& aSelection)
+{
+  // If the selection isn't collapsed, do nothing.
+  if (!aSelection.Collapsed()) {
+    return;
+  }
+
+  NS_ENSURE_TRUE_VOID(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  // Get the (collapsed) selection location
+  NS_ENSURE_TRUE_VOID(aSelection.GetRangeAt(0) &&
+                      aSelection.GetRangeAt(0)->GetStartParent());
+  OwningNonNull<nsINode> selNode = *aSelection.GetRangeAt(0)->GetStartParent();
+  int32_t selOffset = aSelection.GetRangeAt(0)->StartOffset();
 
   // 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.
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->GetPriorHTMLNode(selNode, selOffset, address_of(node), true);
-  if (node && nsTextEditUtils::IsBreak(node))
-  {
-    aSelection->SetInterlinePosition(true);
-    return NS_OK;
-  }
-
-  // are we after a block?  If so try set caret to following content
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->GetPriorHTMLSibling(selNode, selOffset, address_of(node));
-  if (node && IsBlockNode(node))
-  {
-    aSelection->SetInterlinePosition(true);
-    return NS_OK;
-  }
-
-  // are we before a block?  If so try set caret to prior content
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->GetNextHTMLSibling(selNode, selOffset, address_of(node));
-  if (node && IsBlockNode(node))
-    aSelection->SetInterlinePosition(false);
-  return NS_OK;
+  // special-case first so that we don't accidentally fall through into one of
+  // the other conditionals.
+  nsCOMPtr<nsIContent> node =
+    mHTMLEditor->GetPriorHTMLNode(selNode, selOffset, true);
+  if (node && node->IsHTMLElement(nsGkAtoms::br)) {
+    aSelection.SetInterlinePosition(true);
+    return;
+  }
+
+  // Are we after a block?  If so try set caret to following content
+  node = mHTMLEditor->GetPriorHTMLSibling(selNode, selOffset);
+  if (node && IsBlockNode(*node)) {
+    aSelection.SetInterlinePosition(true);
+    return;
+  }
+
+  // Are we before a block?  If so try set caret to prior content
+  node = mHTMLEditor->GetNextHTMLSibling(selNode, selOffset);
+  if (node && IsBlockNode(*node)) {
+    aSelection.SetInterlinePosition(false);
+  }
 }
 
 nsresult
 nsHTMLEditRules::AdjustSelection(Selection* aSelection,
                                  nsIEditor::EDirection aAction)
 {
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
 
@@ -7932,30 +7676,29 @@ nsHTMLEditRules::SelectionEndpointInNode
         *aResult = true;
         return NS_OK;
       }
     }
   }
   return NS_OK;
 }
 
-///////////////////////////////////////////////////////////////////////////
-// IsEmptyInline:  return true if aNode is an empty inline container
-//
-//
+/**
+ * IsEmptyInline: Return true if aNode is an empty inline container
+ */
 bool
-nsHTMLEditRules::IsEmptyInline(nsIDOMNode *aNode)
-{
-  if (aNode && IsInlineNode(aNode) && mHTMLEditor &&
-      mHTMLEditor->IsContainer(aNode))
-  {
-    bool bEmpty;
-    NS_ENSURE_TRUE(mHTMLEditor, false);
-    mHTMLEditor->IsEmptyNode(aNode, &bEmpty);
-    return bEmpty;
+nsHTMLEditRules::IsEmptyInline(nsINode& aNode)
+{
+  NS_ENSURE_TRUE(mHTMLEditor, false);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  if (IsInlineNode(aNode) && mHTMLEditor->IsContainer(&aNode)) {
+    bool isEmpty = true;
+    mHTMLEditor->IsEmptyNode(&aNode, &isEmpty);
+    return isEmpty;
   }
   return false;
 }
 
 
 bool
 nsHTMLEditRules::ListIsEmptyLine(nsTArray<OwningNonNull<nsINode>>& aArrayOfNodes)
 {
@@ -7974,17 +7717,17 @@ nsHTMLEditRules::ListIsEmptyLine(nsTArra
       continue;
     }
     if (nsTextEditUtils::IsBreak(node)) {
       // First break doesn't count
       if (brCount) {
         return false;
       }
       brCount++;
-    } else if (IsEmptyInline(GetAsDOMNode(node))) {
+    } else if (IsEmptyInline(node)) {
       // Empty inline, keep looking
     } else {
       return false;
     }
   }
   return true;
 }
 
@@ -8037,64 +7780,55 @@ nsHTMLEditRules::PopListItem(nsIDOMNode 
   NS_ENSURE_STATE(mHTMLEditor);
   res = mHTMLEditor->MoveNode(listItem, curParPar, parOffset);
   NS_ENSURE_SUCCESS(res, res);
 
   // unwrap list item contents if they are no longer in a list
   if (!nsHTMLEditUtils::IsList(curParPar) &&
       nsHTMLEditUtils::IsListItem(listItem)) {
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->RemoveBlockContainer(GetAsDOMNode(listItem));
+    res = mHTMLEditor->RemoveBlockContainer(*listItem);
     NS_ENSURE_SUCCESS(res, res);
     *aOutOfList = true;
   }
   return res;
 }
 
 nsresult
-nsHTMLEditRules::RemoveListStructure(nsIDOMNode *aList)
-{
-  NS_ENSURE_ARG_POINTER(aList);
-
+nsHTMLEditRules::RemoveListStructure(Element& aList)
+{
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
   nsresult res;
 
-  nsCOMPtr<nsIDOMNode> child;
-  aList->GetFirstChild(getter_AddRefs(child));
-
-  while (child)
-  {
-    if (nsHTMLEditUtils::IsListItem(child))
-    {
-      bool bOutOfList;
-      do
-      {
-        res = PopListItem(child, &bOutOfList);
+  while (aList.GetFirstChild()) {
+    OwningNonNull<nsIContent> child = *aList.GetFirstChild();
+
+    if (nsHTMLEditUtils::IsListItem(child)) {
+      bool isOutOfList;
+      // Keep popping it out until it's not in a list anymore
+      do {
+        res = PopListItem(child->AsDOMNode(), &isOutOfList);
         NS_ENSURE_SUCCESS(res, res);
-      } while (!bOutOfList);   // keep popping it out until it's not in a list anymore
-    }
-    else if (nsHTMLEditUtils::IsList(child))
-    {
-      res = RemoveListStructure(child);
+      } while (!isOutOfList);
+    } else if (nsHTMLEditUtils::IsList(child)) {
+      res = RemoveListStructure(*child->AsElement());
       NS_ENSURE_SUCCESS(res, res);
-    }
-    else
-    {
-      // delete any non- list items for now
-      NS_ENSURE_STATE(mHTMLEditor);
+    } else {
+      // Delete any non-list items for now
       res = mHTMLEditor->DeleteNode(child);
       NS_ENSURE_SUCCESS(res, res);
     }
-    aList->GetFirstChild(getter_AddRefs(child));
-  }
-  // delete the now-empty list
-  NS_ENSURE_STATE(mHTMLEditor);
+  }
+
+  // Delete the now-empty list
   res = mHTMLEditor->RemoveBlockContainer(aList);
   NS_ENSURE_SUCCESS(res, res);
 
-  return res;
+  return NS_OK;
 }
 
 
 nsresult
 nsHTMLEditRules::ConfirmSelectionInBody()
 {
   // get the body
   NS_ENSURE_STATE(mHTMLEditor);
@@ -8217,30 +7951,31 @@ nsHTMLEditRules::UpdateDocChangeRange(ns
       res = mDocChangeRange->SetEnd(endNode, endOffset);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return res;
 }
 
 nsresult
-nsHTMLEditRules::InsertMozBRIfNeeded(nsIDOMNode *aNode)
-{
-  NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
-  if (!IsBlockNode(aNode)) return NS_OK;
+nsHTMLEditRules::InsertMozBRIfNeeded(nsINode& aNode)
+{
+  if (!IsBlockNode(aNode)) {
+    return NS_OK;
+  }
 
   bool isEmpty;
   NS_ENSURE_STATE(mHTMLEditor);
-  nsresult res = mHTMLEditor->IsEmptyNode(aNode, &isEmpty);
+  nsresult res = mHTMLEditor->IsEmptyNode(&aNode, &isEmpty);
   NS_ENSURE_SUCCESS(res, res);
   if (!isEmpty) {
     return NS_OK;
   }
 
-  return CreateMozBR(aNode, 0);
+  return CreateMozBR(aNode.AsDOMNode(), 0);
 }
 
 NS_IMETHODIMP
 nsHTMLEditRules::WillCreateNode(const nsAString& aTag, nsIDOMNode *aParent, int32_t aPosition)
 {
   return NS_OK;
 }
 
@@ -8622,366 +8357,322 @@ nsHTMLEditRules::MakeSureElemStartsOrEnd
 {
   nsresult res = MakeSureElemStartsOrEndsOnCR(aNode, false);
   NS_ENSURE_SUCCESS(res, res);
   res = MakeSureElemStartsOrEndsOnCR(aNode, true);
   return res;
 }
 
 nsresult
-nsHTMLEditRules::AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly)
-{
-  NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
-
-  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
-  bool isBlock = IsBlockNode(node);
-  if (!isBlock && !nsHTMLEditUtils::IsHR(node)) {
-    // we deal only with blocks; early way out
+nsHTMLEditRules::AlignBlock(Element& aElement, const nsAString& aAlignType,
+                            ContentsOnly aContentsOnly)
+{
+  if (!IsBlockNode(aElement) && !aElement.IsHTMLElement(nsGkAtoms::hr)) {
+    // We deal only with blocks; early way out
     return NS_OK;
   }
 
-  nsresult res = RemoveAlignment(node, *aAlignType, aContentsOnly);
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  nsresult res = RemoveAlignment(aElement.AsDOMNode(), aAlignType,
+                                 aContentsOnly == ContentsOnly::yes);
   NS_ENSURE_SUCCESS(res, res);
   NS_NAMED_LITERAL_STRING(attr, "align");
-  NS_ENSURE_STATE(mHTMLEditor);
   if (mHTMLEditor->IsCSSEnabled()) {
-    // let's use CSS alignment; we use margin-left and margin-right for tables
+    // Let's use CSS alignment; we use margin-left and margin-right for tables
     // and text-align for other block-level elements
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->SetAttributeOrEquivalent(aElement, attr, *aAlignType, false);
+    res = mHTMLEditor->SetAttributeOrEquivalent(
+      static_cast<nsIDOMElement*>(aElement.AsDOMNode()), attr, aAlignType,
+      false);
     NS_ENSURE_SUCCESS(res, res);
-  }
-  else {
+  } else {
     // HTML case; this code is supposed to be called ONLY if the element
     // supports the align attribute but we'll never know...
-    if (nsHTMLEditUtils::SupportsAlignAttr(node)) {
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->SetAttribute(aElement, attr, *aAlignType);
+    if (nsHTMLEditUtils::SupportsAlignAttr(aElement.AsDOMNode())) {
+      res =
+        mHTMLEditor->SetAttribute(static_cast<nsIDOMElement*>(aElement.AsDOMNode()),
+                                  attr, aAlignType);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return NS_OK;
 }
 
 nsresult
-nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, int8_t aRelativeChange)
-{
-  NS_ENSURE_ARG_POINTER(aNode);
-
-  if (aRelativeChange != 1 && aRelativeChange != -1) {
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-
-  nsCOMPtr<Element> element = do_QueryInterface(aNode);
-  if (!element) {
-    return NS_OK;
-  }
-
+nsHTMLEditRules::ChangeIndentation(Element& aElement, Change aChange)
+{
   NS_ENSURE_STATE(mHTMLEditor);
-  nsIAtom* marginProperty =
-    MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils,
-                                GetAsDOMNode(element));
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  nsIAtom& marginProperty =
+    MarginPropertyAtomForIndent(*mHTMLEditor->mHTMLCSSUtils, aElement);
   nsAutoString value;
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*element, *marginProperty,
+  mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(aElement, marginProperty,
                                                    value);
   float f;
   nsCOMPtr<nsIAtom> unit;
-  NS_ENSURE_STATE(mHTMLEditor);
   mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit));
   if (0 == f) {
     nsAutoString defaultLengthUnit;
-    NS_ENSURE_STATE(mHTMLEditor);
     mHTMLEditor->mHTMLCSSUtils->GetDefaultLengthUnit(defaultLengthUnit);
     unit = NS_Atomize(defaultLengthUnit);
   }
+  int8_t multiplier = aChange == Change::plus ? +1 : -1;
   if        (nsGkAtoms::in == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_IN * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_IN * multiplier;
   } else if (nsGkAtoms::cm == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_CM * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_CM * multiplier;
   } else if (nsGkAtoms::mm == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_MM * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_MM * multiplier;
   } else if (nsGkAtoms::pt == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_PT * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_PT * multiplier;
   } else if (nsGkAtoms::pc == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_PC * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_PC * multiplier;
   } else if (nsGkAtoms::em == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_EM * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_EM * multiplier;
   } else if (nsGkAtoms::ex == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_EX * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_EX * multiplier;
   } else if (nsGkAtoms::px == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_PX * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_PX * multiplier;
   } else if (nsGkAtoms::percentage == unit) {
-            f += NS_EDITOR_INDENT_INCREMENT_PERCENT * aRelativeChange;
+            f += NS_EDITOR_INDENT_INCREMENT_PERCENT * multiplier;
   }
 
   if (0 < f) {
     nsAutoString newValue;
     newValue.AppendFloat(f);
     newValue.Append(nsDependentAtomString(unit));
-    NS_ENSURE_STATE(mHTMLEditor);
-    mHTMLEditor->mHTMLCSSUtils->SetCSSProperty(*element, *marginProperty,
+    mHTMLEditor->mHTMLCSSUtils->SetCSSProperty(aElement, marginProperty,
                                                newValue);
     return NS_OK;
   }
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->mHTMLCSSUtils->RemoveCSSProperty(*element, *marginProperty,
+  mHTMLEditor->mHTMLCSSUtils->RemoveCSSProperty(aElement, marginProperty,
                                                 value);
 
-  // remove unnecessary DIV blocks:
-  // we could skip this section but that would cause a FAIL in
-  // editor/libeditor/tests/browserscope/richtext.html, which expects
-  // to unapply a CSS "indent" (<div style="margin-left: 40px;">) by
-  // removing the DIV container instead of just removing the CSS property.
-  nsCOMPtr<dom::Element> node = do_QueryInterface(aNode);
-  if (!node || !node->IsHTMLElement(nsGkAtoms::div) ||
-      !mHTMLEditor ||
-      node == mHTMLEditor->GetActiveEditingHost() ||
-      !mHTMLEditor->IsDescendantOfEditorRoot(node) ||
-      nsHTMLEditor::HasAttributes(node)) {
-    NS_ENSURE_STATE(mHTMLEditor);
+  // Remove unnecessary divs
+  if (!aElement.IsHTMLElement(nsGkAtoms::div) ||
+      &aElement == mHTMLEditor->GetActiveEditingHost() ||
+      !mHTMLEditor->IsDescendantOfEditorRoot(&aElement) ||
+      nsHTMLEditor::HasAttributes(&aElement)) {
     return NS_OK;
   }
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  return mHTMLEditor->RemoveContainer(node);
+  nsresult res = mHTMLEditor->RemoveContainer(&aElement);
+  NS_ENSURE_SUCCESS(res, res);
+
+  return NS_OK;
 }
 
 //
 // Support for Absolute Positioning
 //
 
 nsresult
-nsHTMLEditRules::WillAbsolutePosition(Selection* aSelection,
+nsHTMLEditRules::WillAbsolutePosition(Selection& aSelection,
                                       bool* aCancel, bool* aHandled)
 {
-  if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
-  WillInsert(*aSelection, aCancel);
-
-  // initialize out param
-  // we want to ignore result of WillInsert()
+  MOZ_ASSERT(aCancel && aHandled);
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  WillInsert(aSelection, aCancel);
+
+  // We want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = true;
 
-  nsCOMPtr<nsIDOMElement> focusElement;
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsresult res =
-    mHTMLEditor->GetSelectionContainer(getter_AddRefs(focusElement));
-  if (focusElement) {
-    nsCOMPtr<nsIDOMNode> node = do_QueryInterface(focusElement);
-    if (nsHTMLEditUtils::IsImage(node)) {
-      mNewBlock = node;
-      return NS_OK;
-    }
-  }
-
-  res = NormalizeSelection(aSelection);
+  nsCOMPtr<Element> focusElement = mHTMLEditor->GetSelectionContainer();
+  if (focusElement && nsHTMLEditUtils::IsImage(focusElement)) {
+    mNewBlock = focusElement;
+    return NS_OK;
+  }
+
+  nsresult res = NormalizeSelection(&aSelection);
   NS_ENSURE_SUCCESS(res, res);
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
-
-  // 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
+  nsAutoSelectionReset selectionResetter(&aSelection, mHTMLEditor);
+
+  // 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,
+  GetPromotedRanges(aSelection, arrayOfRanges,
                     EditAction::setAbsolutePosition);
 
-  // use these ranges to contruct a list of nodes to act on.
+  // Use these ranges to contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   res = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
                              EditAction::setAbsolutePosition);
   NS_ENSURE_SUCCESS(res, res);
 
-  // if nothing visible in list, make an empty block
-  if (ListIsEmptyLine(arrayOfNodes))
-  {
-    // get selection location
-    NS_ENSURE_STATE(aSelection->RangeCount());
-    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
-    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
-    NS_ENSURE_STATE(parent);
-
-    // make sure we can put a block here
+  // If nothing visible in list, make an empty block
+  if (ListIsEmptyLine(arrayOfNodes)) {
+    // Get selection location
+    NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
+                    aSelection.GetRangeAt(0)->GetStartParent());
+    OwningNonNull<nsINode> parent =
+      *aSelection.GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
+
+    // Make sure we can put a block here
     res = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
     NS_ENSURE_SUCCESS(res, res);
-    NS_ENSURE_STATE(mHTMLEditor);
-    nsCOMPtr<Element> thePositionedDiv =
+    nsCOMPtr<Element> positionedDiv =
       mHTMLEditor->CreateNode(nsGkAtoms::div, parent, offset);
-    NS_ENSURE_STATE(thePositionedDiv);
-    // remember our new block for postprocessing
-    mNewBlock = thePositionedDiv->AsDOMNode();
-    // delete anything that was in the list of nodes
+    NS_ENSURE_STATE(positionedDiv);
+    // 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];
-      NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       arrayOfNodes.RemoveElementAt(0);
     }
-    // put selection in new block
-    res = aSelection->Collapse(thePositionedDiv,0);
-    selectionResetter.Abort();  // to prevent selection reseter from overriding us.
+    // Put selection in new block
+    res = aSelection.Collapse(positionedDiv, 0);
+    // Prevent selection resetter from overriding us.
+    selectionResetter.Abort();
     *aHandled = true;
-    return res;
-  }
-
-  // Ok, now go through all the nodes and put them in a blockquote,
-  // or whatever is appropriate.  Wohoo!
-  nsCOMPtr<nsINode> curParent;
-  nsCOMPtr<nsIDOMNode> indentedLI, sibling;
-  nsCOMPtr<Element> curList, curPositionedDiv;
+    NS_ENSURE_SUCCESS(res, res);
+    return NS_OK;
+  }
+
+  // Okay, now go through all the nodes and put them in a blockquote, or
+  // whatever is appropriate.  Woohoo!
+  nsCOMPtr<Element> curList, curPositionedDiv, indentedLI;
   for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
-    // here's where we actually figure out what to do
+    // Here's where we actually figure out what to do
     NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
-    nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent();
+    OwningNonNull<nsIContent> curNode = *arrayOfNodes[i]->AsContent();
 
     // Ignore all non-editable nodes.  Leave them be.
-    NS_ENSURE_STATE(mHTMLEditor);
-    if (!mHTMLEditor->IsEditable(curNode)) continue;
-
-    curParent = curNode->GetParentNode();
+    if (!mHTMLEditor->IsEditable(curNode)) {
+      continue;
+    }
+
+    nsCOMPtr<nsIContent> sibling;
+
+    nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
     int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
 
-    // some logic for putting list items into nested lists...
-    if (nsHTMLEditUtils::IsList(curParent))
-    {
-      // check to see if curList is still appropriate.  Which it is if
-      // curNode is still right after it in the same list.
-      if (curList)
-      {
-        NS_ENSURE_STATE(mHTMLEditor);
-        sibling = GetAsDOMNode(mHTMLEditor->GetPriorHTMLSibling(curNode));
-      }
-
-      if (!curList || (sibling && sibling != GetAsDOMNode(curList))) {
-        // create a new nested list of correct type
+    // Some logic for putting list items into nested lists...
+    if (nsHTMLEditUtils::IsList(curParent)) {
+      // 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 = mHTMLEditor->GetPriorHTMLSibling(curNode);
+      }
+
+      if (!curList || (sibling && sibling != curList)) {
+        // Create a new nested list of correct type
         res = SplitAsNeeded(*curParent->NodeInfo()->NameAtom(), curParent,
                             offset);
         NS_ENSURE_SUCCESS(res, res);
         if (!curPositionedDiv) {
           nsCOMPtr<nsINode> curParentParent = curParent->GetParentNode();
           int32_t parentOffset = curParentParent
             ? curParentParent->IndexOf(curParent) : -1;
-          NS_ENSURE_STATE(mHTMLEditor);
           curPositionedDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, curParentParent,
                                                      parentOffset);
-          mNewBlock = GetAsDOMNode(curPositionedDiv);
+          mNewBlock = curPositionedDiv;
         }
-        NS_ENSURE_STATE(mHTMLEditor);
         curList = mHTMLEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
                                           curPositionedDiv, -1);
         NS_ENSURE_STATE(curList);
-        // 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
-      NS_ENSURE_STATE(mHTMLEditor);
+        // 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
       res = mHTMLEditor->MoveNode(curNode, curList, -1);
       NS_ENSURE_SUCCESS(res, res);
-      // forget curPositionedDiv, if any
-      // curPositionedDiv = nullptr;
-    }
-
-    else // 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 have several nodes listed in the
-      // array of nodes to act on, that are in the same list item.  Since
-      // we only want to indent that li once, we must keep track of the most
-      // recent indented list item, and not indent it if we find another node
-      // to act on that is still inside the same li.
+    } else {
+      // 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
+      // have several nodes listed in the array of nodes to act on, that are in
+      // the same list item.  Since we only want to indent that li once, we
+      // must keep track of the most recent indented list item, and not indent
+      // it if we find another node to act on that is still inside the same li.
       nsCOMPtr<Element> listItem = IsInListItem(curNode);
       if (listItem) {
-        if (indentedLI == GetAsDOMNode(listItem)) {
-          // already indented this list item
+        if (indentedLI == listItem) {
+          // Already indented this list item
           continue;
         }
         curParent = listItem->GetParentNode();
         offset = curParent ? curParent->IndexOf(listItem) : -1;
-        // check to see if curList is still appropriate.  Which it is if
+        // Check to see if curList is still appropriate.  Which it is if
         // curNode is still right after it in the same list.
-        if (curList)
-        {
-          NS_ENSURE_STATE(mHTMLEditor);
-          sibling = GetAsDOMNode(mHTMLEditor->GetPriorHTMLSibling(curNode));
+        if (curList) {
+          sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
         }
 
-        if (!curList || (sibling && sibling != GetAsDOMNode(curList))) {
-          // create a new nested list of correct type
+        if (!curList || (sibling && sibling != curList)) {
+          // Create a new nested list of correct type
           res = SplitAsNeeded(*curParent->NodeInfo()->NameAtom(), curParent,
                               offset);
           NS_ENSURE_SUCCESS(res, res);
           if (!curPositionedDiv) {
             nsCOMPtr<nsINode> curParentParent = curParent->GetParentNode();
             int32_t parentOffset = curParentParent ?
               curParentParent->IndexOf(curParent) : -1;
-            NS_ENSURE_STATE(mHTMLEditor);
             curPositionedDiv = mHTMLEditor->CreateNode(nsGkAtoms::div,
                                                        curParentParent,
                                                        parentOffset);
-            mNewBlock = GetAsDOMNode(curPositionedDiv);
+            mNewBlock = curPositionedDiv;
           }
-          NS_ENSURE_STATE(mHTMLEditor);
           curList = mHTMLEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
                                             curPositionedDiv, -1);
           NS_ENSURE_STATE(curList);
         }
-        NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->MoveNode(listItem, curList, -1);
         NS_ENSURE_SUCCESS(res, res);
-        // remember we indented this li
-        indentedLI = GetAsDOMNode(listItem);
-      }
-
-      else
-      {
-        // need to make a div to put things in if we haven't already
-
-        if (!curPositionedDiv)
-        {
+        // Remember we indented this li
+        indentedLI = listItem;
+      } else {
+        // Need to make a div to put things in if we haven't already
+
+        if (!curPositionedDiv) {
           if (curNode->IsHTMLElement(nsGkAtoms::div)) {
             curPositionedDiv = curNode->AsElement();
-            mNewBlock = GetAsDOMNode(curPositionedDiv);
+            mNewBlock = curPositionedDiv;
             curList = nullptr;
             continue;
           }
           res = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
           NS_ENSURE_SUCCESS(res, res);
-          NS_ENSURE_STATE(mHTMLEditor);
           curPositionedDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, curParent,
                                                      offset);
           NS_ENSURE_STATE(curPositionedDiv);
-          // remember our new block for postprocessing
-          mNewBlock = GetAsDOMNode(curPositionedDiv);
+          // 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
-        NS_ENSURE_STATE(mHTMLEditor);
+        // Tuck the node into the end of the active blockquote
         res = mHTMLEditor->MoveNode(curNode, curPositionedDiv, -1);
         NS_ENSURE_SUCCESS(res, res);
-        // forget curList, if any
+        // Forget curList, if any
         curList = nullptr;
       }
     }
   }
-  return res;
+  return NS_OK;
 }
 
 nsresult
 nsHTMLEditRules::DidAbsolutePosition()
 {
   NS_ENSURE_STATE(mHTMLEditor);
   nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
-  nsCOMPtr<nsIDOMElement> elt = do_QueryInterface(mNewBlock);
+  nsCOMPtr<nsIDOMElement> elt =
+    static_cast<nsIDOMElement*>(GetAsDOMNode(mNewBlock));
   return absPosHTMLEditor->AbsolutelyPositionElement(elt, true);
 }
 
 nsresult
 nsHTMLEditRules::WillRemoveAbsolutePosition(Selection* aSelection,
                                             bool* aCancel, bool* aHandled) {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   WillInsert(*aSelection, aCancel);
--- a/editor/libeditor/nsHTMLEditRules.h
+++ b/editor/libeditor/nsHTMLEditRules.h
@@ -70,20 +70,20 @@ public:
 
   // nsIEditRules methods
   NS_IMETHOD Init(nsPlaintextEditor *aEditor) override;
   NS_IMETHOD DetachEditor() override;
   NS_IMETHOD BeforeEdit(EditAction action,
                         nsIEditor::EDirection aDirection) override;
   NS_IMETHOD AfterEdit(EditAction action,
                        nsIEditor::EDirection aDirection) override;
-  NS_IMETHOD WillDoAction(mozilla::dom::Selection* aSelection, nsRulesInfo* aInfo,
+  NS_IMETHOD WillDoAction(Selection* aSelection, nsRulesInfo* aInfo,
                           bool* aCancel, bool* aHandled) override;
-  NS_IMETHOD DidDoAction(mozilla::dom::Selection* aSelection,
-                         nsRulesInfo* aInfo, nsresult aResult) override;
+  NS_IMETHOD DidDoAction(Selection* aSelection, nsRulesInfo* aInfo,
+                         nsresult aResult) override;
   NS_IMETHOD DocumentModified() override;
 
   nsresult GetListState(bool *aMixed, bool *aOL, bool *aUL, bool *aDL);
   nsresult GetListItemState(bool *aMixed, bool *aLI, bool *aDT, bool *aDD);
   nsresult GetIndentState(bool *aCanIndent, bool *aCanOutdent);
   nsresult GetAlignment(bool *aMixed, nsIHTMLEditor::EAlignment *aAlign);
   nsresult GetParagraphState(bool *aMixed, nsAString &outFormat);
   nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode);
@@ -112,218 +112,199 @@ protected:
   virtual ~nsHTMLEditRules();
 
   enum RulesEndpoint
   {
     kStart,
     kEnd
   };
 
-  enum BRLocation
-  {
-    kBeforeBlock,
-    kBlockEnd
-  };
-
   void InitFields();
 
   // nsHTMLEditRules implementation methods
-  void WillInsert(mozilla::dom::Selection& aSelection, bool* aCancel);
+  void WillInsert(Selection& aSelection, bool* aCancel);
   nsresult WillInsertText(  EditAction aAction,
-                            mozilla::dom::Selection* aSelection,
+                            Selection* aSelection,
                             bool            *aCancel,
                             bool            *aHandled,
                             const nsAString *inString,
                             nsAString       *outString,
                             int32_t          aMaxLength);
-  nsresult WillLoadHTML(mozilla::dom::Selection* aSelection, bool* aCancel);
-  nsresult WillInsertBreak(mozilla::dom::Selection& aSelection,
-                           bool* aCancel, bool* aHandled);
+  nsresult WillLoadHTML(Selection* aSelection, bool* aCancel);
+  nsresult WillInsertBreak(Selection& aSelection, bool* aCancel,
+                           bool* aHandled);
   nsresult StandardBreakImpl(nsINode& aNode, int32_t aOffset,
-                             mozilla::dom::Selection& aSelection);
-  nsresult DidInsertBreak(mozilla::dom::Selection* aSelection,
-                          nsresult aResult);
-  nsresult SplitMailCites(mozilla::dom::Selection* aSelection, bool* aHandled);
-  nsresult WillDeleteSelection(mozilla::dom::Selection* aSelection,
+                             Selection& aSelection);
+  nsresult DidInsertBreak(Selection* aSelection, nsresult aResult);
+  nsresult SplitMailCites(Selection* aSelection, bool* aHandled);
+  nsresult WillDeleteSelection(Selection* aSelection,
                                nsIEditor::EDirection aAction,
                                nsIEditor::EStripWrappers aStripWrappers,
                                bool* aCancel, bool* aHandled);
-  nsresult DidDeleteSelection(mozilla::dom::Selection* aSelection,
+  nsresult DidDeleteSelection(Selection* aSelection,
                               nsIEditor::EDirection aDir,
                               nsresult aResult);
-  nsresult InsertBRIfNeeded(mozilla::dom::Selection* aSelection);
+  nsresult InsertBRIfNeeded(Selection* aSelection);
   ::DOMPoint GetGoodSelPointForNode(nsINode& aNode,
                                     nsIEditor::EDirection aAction);
   nsresult JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
                       bool* aCanceled);
-  nsresult MoveBlock(nsIDOMNode *aLeft, nsIDOMNode *aRight, int32_t aLeftOffset, int32_t aRightOffset);
-  nsresult MoveNodeSmart(nsIDOMNode *aSource, nsIDOMNode *aDest, int32_t *aOffset);
-  nsresult MoveContents(nsIDOMNode *aSource, nsIDOMNode *aDest, int32_t *aOffset);
+  nsresult MoveBlock(Element& aLeftBlock, Element& aRightBlock,
+                     int32_t aLeftOffset, int32_t aRightOffset);
+  nsresult MoveNodeSmart(nsIContent& aNode, Element& aDestElement,
+                         int32_t* aOffset);
+  nsresult MoveContents(Element& aElement, Element& aDestElement,
+                        int32_t* aOffset);
   nsresult DeleteNonTableElements(nsINode* aNode);
-  nsresult WillMakeList(mozilla::dom::Selection* aSelection,
+  nsresult WillMakeList(Selection* aSelection,
                         const nsAString* aListType,
                         bool aEntireList,
                         const nsAString* aBulletType,
                         bool* aCancel, bool* aHandled,
                         const nsAString* aItemType = nullptr);
-  nsresult WillRemoveList(mozilla::dom::Selection* aSelection,
-                          bool aOrdered, bool* aCancel, bool* aHandled);
-  nsresult WillIndent(mozilla::dom::Selection* aSelection,
-                      bool* aCancel, bool* aHandled);
-  nsresult WillCSSIndent(mozilla::dom::Selection* aSelection,
-                         bool* aCancel, bool* aHandled);
-  nsresult WillHTMLIndent(mozilla::dom::Selection* aSelection,
-                          bool* aCancel, bool* aHandled);
-  nsresult WillOutdent(mozilla::dom::Selection* aSelection,
-                       bool* aCancel, bool* aHandled);
-  nsresult WillAlign(mozilla::dom::Selection* aSelection,
-                     const nsAString* alignType,
+  nsresult WillRemoveList(Selection* aSelection, bool aOrdered, bool* aCancel,
+                          bool* aHandled);
+  nsresult WillIndent(Selection* aSelection, bool* aCancel, bool* aHandled);
+  nsresult WillCSSIndent(Selection* aSelection, bool* aCancel, bool* aHandled);
+  nsresult WillHTMLIndent(Selection* aSelection, bool* aCancel,
+                          bool* aHandled);
+  nsresult WillOutdent(Selection& aSelection, bool* aCancel, bool* aHandled);
+  nsresult WillAlign(Selection& aSelection, const nsAString& aAlignType,
                      bool* aCancel, bool* aHandled);
-  nsresult WillAbsolutePosition(mozilla::dom::Selection* aSelection,
-                                bool* aCancel, bool* aHandled);
-  nsresult WillRemoveAbsolutePosition(mozilla::dom::Selection* aSelection,
-                                      bool* aCancel, bool* aHandled);
-  nsresult WillRelativeChangeZIndex(mozilla::dom::Selection* aSelection,
-                                    int32_t aChange,
+  nsresult WillAbsolutePosition(Selection& aSelection, bool* aCancel,
+                                bool* aHandled);
+  nsresult WillRemoveAbsolutePosition(Selection* aSelection, bool* aCancel,
+                                      bool* aHandled);
+  nsresult WillRelativeChangeZIndex(Selection* aSelection, int32_t aChange,
                                     bool* aCancel, bool* aHandled);
-  nsresult WillMakeDefListItem(mozilla::dom::Selection* aSelection,
+  nsresult WillMakeDefListItem(Selection* aSelection,
                                const nsAString* aBlockType, bool aEntireList,
                                bool* aCancel, bool* aHandled);
-  nsresult WillMakeBasicBlock(mozilla::dom::Selection* aSelection,
-                              const nsAString* aBlockType,
+  nsresult WillMakeBasicBlock(Selection& aSelection,
+                              const nsAString& aBlockType,
                               bool* aCancel, bool* aHandled);
-  nsresult DidMakeBasicBlock(mozilla::dom::Selection* aSelection,
-                             nsRulesInfo* aInfo, nsresult aResult);
+  nsresult DidMakeBasicBlock(Selection* aSelection, nsRulesInfo* aInfo,
+                             nsresult aResult);
   nsresult DidAbsolutePosition();
   nsresult AlignInnerBlocks(nsINode& aNode, const nsAString* alignType);
   nsresult AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType);
-  nsresult AppendInnerFormatNodes(nsTArray<mozilla::OwningNonNull<nsINode>>& aArray,
+  nsresult AppendInnerFormatNodes(nsTArray<OwningNonNull<nsINode>>& aArray,
                                   nsINode* aNode);
   nsresult GetFormatString(nsIDOMNode *aNode, nsAString &outFormat);
   enum class Lists { no, yes };
   enum class Tables { no, yes };
   void GetInnerContent(nsINode& aNode,
-                       nsTArray<mozilla::OwningNonNull<nsINode>>& aOutArrayOfNodes,
+                       nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
                        int32_t* aIndex, Lists aLists = Lists::yes,
                        Tables aTables = Tables::yes);
-  mozilla::dom::Element* IsInListItem(nsINode* aNode);
-  nsresult ReturnInHeader(mozilla::dom::Selection* aSelection,
-                          nsIDOMNode* aHeader, nsIDOMNode* aTextNode,
-                          int32_t aOffset);
-  nsresult ReturnInParagraph(mozilla::dom::Selection* aSelection,
-                             nsIDOMNode* aHeader, nsIDOMNode* aTextNode,
-                             int32_t aOffset, bool* aCancel, bool* aHandled);
+  Element* IsInListItem(nsINode* aNode);
+  nsresult ReturnInHeader(Selection& aSelection, Element& aHeader,
+                          nsINode& aNode, int32_t aOffset);
+  nsresult ReturnInParagraph(Selection* aSelection, nsIDOMNode* aHeader,
+                             nsIDOMNode* aTextNode, int32_t aOffset,
+                             bool* aCancel, bool* aHandled);
   nsresult SplitParagraph(nsIDOMNode *aPara,
-                          nsIDOMNode *aBRNode,
-                          mozilla::dom::Selection* aSelection,
+                          nsIContent* aBRNode,
+                          Selection* aSelection,
                           nsCOMPtr<nsIDOMNode> *aSelNode,
                           int32_t *aOffset);
-  nsresult ReturnInListItem(mozilla::dom::Selection* aSelection,
-                            nsIDOMNode* aHeader, nsIDOMNode* aTextNode,
-                            int32_t aOffset);
+  nsresult ReturnInListItem(Selection& aSelection, Element& aHeader,
+                            nsINode& aNode, int32_t aOffset);
   nsresult AfterEditInner(EditAction action,
                           nsIEditor::EDirection aDirection);
-  nsresult RemovePartOfBlock(mozilla::dom::Element& aBlock,
-                             nsIContent& aStartChild,
+  nsresult RemovePartOfBlock(Element& aBlock, nsIContent& aStartChild,
                              nsIContent& aEndChild);
-  nsresult SplitBlock(nsIDOMNode *aBlock,
-                      nsIDOMNode *aStartChild,
-                      nsIDOMNode *aEndChild,
-                      nsCOMPtr<nsIDOMNode> *aLeftNode = 0,
-                      nsCOMPtr<nsIDOMNode> *aRightNode = 0,
-                      nsCOMPtr<nsIDOMNode> *aMiddleNode = 0);
-  nsresult OutdentPartOfBlock(nsIDOMNode *aBlock,
-                              nsIDOMNode *aStartChild,
-                              nsIDOMNode *aEndChild,
+  void     SplitBlock(Element& aBlock,
+                      nsIContent& aStartChild,
+                      nsIContent& aEndChild,
+                      nsIContent** aOutLeftNode = nullptr,
+                      nsIContent** aOutRightNode = nullptr,
+                      nsIContent** aOutMiddleNode = nullptr);
+  nsresult OutdentPartOfBlock(Element& aBlock,
+                              nsIContent& aStartChild,
+                              nsIContent& aEndChild,
                               bool aIsBlockIndentedWithCSS,
-                              nsCOMPtr<nsIDOMNode> *aLeftNode = 0,
-                              nsCOMPtr<nsIDOMNode> *aRightNode = 0);
+                              nsIContent** aOutLeftNode,
+                              nsIContent** aOutRightNode);
 
-  nsresult ConvertListType(nsIDOMNode* aList,
-                           nsCOMPtr<nsIDOMNode>* outList,
-                           nsIAtom* aListType,
-                           nsIAtom* aItemType);
-  nsresult ConvertListType(mozilla::dom::Element* aList,
-                           mozilla::dom::Element** aOutList,
-                           nsIAtom* aListType,
-                           nsIAtom* aItemType);
+  nsresult ConvertListType(Element* aList, Element** aOutList,
+                           nsIAtom* aListType, nsIAtom* aItemType);
 
-  nsresult CreateStyleForInsertText(mozilla::dom::Selection* aSelection,
-                                    nsIDOMDocument* aDoc);
-  nsresult IsEmptyBlock(nsIDOMNode *aNode,
-                        bool *outIsEmptyBlock,
-                        bool aMozBRDoesntCount = false,
-                        bool aListItemsNotEmpty = false);
-  nsresult CheckForEmptyBlock(nsINode* aStartNode,
-                              mozilla::dom::Element* aBodyNode,
-                              mozilla::dom::Selection* aSelection,
-                              nsIEditor::EDirection aAction,
-                              bool* aHandled);
-  nsresult CheckForInvisibleBR(nsIDOMNode *aBlock, nsHTMLEditRules::BRLocation aWhere,
-                               nsCOMPtr<nsIDOMNode> *outBRNode, int32_t aOffset=0);
-  nsresult ExpandSelectionForDeletion(mozilla::dom::Selection* aSelection);
+  nsresult CreateStyleForInsertText(Selection& aSelection, nsIDocument& aDoc);
+  enum class MozBRCounts { yes, no };
+  nsresult IsEmptyBlock(Element& aNode, bool* aOutIsEmptyBlock,
+                        MozBRCounts aMozBRCounts = MozBRCounts::yes);
+  nsresult CheckForEmptyBlock(nsINode* aStartNode, Element* aBodyNode,
+                              Selection* aSelection,
+                              nsIEditor::EDirection aAction, bool* aHandled);
+  enum class BRLocation { beforeBlock, blockEnd };
+  Element* CheckForInvisibleBR(Element& aBlock, BRLocation aWhere,
+                               int32_t aOffset = 0);
+  nsresult ExpandSelectionForDeletion(Selection& aSelection);
   bool IsFirstNode(nsIDOMNode *aNode);
   bool IsLastNode(nsIDOMNode *aNode);
-  nsresult NormalizeSelection(mozilla::dom::Selection* aSelection);
+  nsresult NormalizeSelection(Selection* aSelection);
   void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode,
                         int32_t aOffset, EditAction actionID,
                         nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset);
-  void GetPromotedRanges(mozilla::dom::Selection& aSelection,
+  void GetPromotedRanges(Selection& aSelection,
                          nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
                          EditAction inOperationType);
   void PromoteRange(nsRange& aRange, EditAction inOperationType);
   enum class TouchContent { no, yes };
   nsresult GetNodesForOperation(nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
-                                nsTArray<mozilla::OwningNonNull<nsINode>>& aOutArrayOfNodes,
+                                nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
                                 EditAction aOperationType,
                                 TouchContent aTouchContent = TouchContent::yes);
   void GetChildNodesForOperation(nsINode& aNode,
-      nsTArray<mozilla::OwningNonNull<nsINode>>& outArrayOfNodes);
+      nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes);
   nsresult GetNodesFromPoint(::DOMPoint aPoint,
                              EditAction aOperation,
-                             nsTArray<mozilla::OwningNonNull<nsINode>>& outArrayOfNodes,
+                             nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
                              TouchContent aTouchContent);
-  nsresult GetNodesFromSelection(mozilla::dom::Selection& aSelection,
+  nsresult GetNodesFromSelection(Selection& aSelection,
                                  EditAction aOperation,
-                                 nsTArray<mozilla::OwningNonNull<nsINode>>& outArrayOfNodes,
+                                 nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
                                  TouchContent aTouchContent = TouchContent::yes);
   enum class EntireList { no, yes };
-  nsresult GetListActionNodes(nsTArray<mozilla::OwningNonNull<nsINode>>& aOutArrayOfNodes,
+  nsresult GetListActionNodes(nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
                               EntireList aEntireList,
                               TouchContent aTouchContent = TouchContent::yes);
-  void GetDefinitionListItemTypes(mozilla::dom::Element* aElement, bool* aDT, bool* aDD);
+  void GetDefinitionListItemTypes(Element* aElement, bool* aDT, bool* aDD);
   nsresult GetParagraphFormatNodes(
-      nsTArray<mozilla::OwningNonNull<nsINode>>& outArrayOfNodes,
+      nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
       TouchContent aTouchContent = TouchContent::yes);
-  void LookInsideDivBQandList(nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeArray);
+  void LookInsideDivBQandList(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
   nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange);
   nsresult BustUpInlinesAtBRs(nsIContent& aNode,
-                              nsTArray<mozilla::OwningNonNull<nsINode>>& aOutArrayOfNodes);
-  nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode);
-  void MakeTransitionList(nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeArray,
+                              nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes);
+  nsIContent* GetHighestInlineParent(nsINode& aNode);
+  void MakeTransitionList(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
                           nsTArray<bool>& aTransitionArray);
-  nsresult RemoveBlockStyle(nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeArray);
-  nsresult ApplyBlockStyle(nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeArray,
+  nsresult RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
+  nsresult ApplyBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
                            nsIAtom& aBlockTag);
-  nsresult MakeBlockquote(nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeArray);
+  nsresult MakeBlockquote(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
+  nsresult SplitAsNeeded(nsIAtom& aTag, OwningNonNull<nsINode>& inOutParent,
+                         int32_t& inOutOffset);
   nsresult SplitAsNeeded(nsIAtom& aTag, nsCOMPtr<nsINode>& inOutParent,
                          int32_t& inOutOffset);
   nsresult AddTerminatingBR(nsIDOMNode *aBlock);
   ::DOMPoint JoinNodesSmart(nsIContent& aNodeLeft, nsIContent& aNodeRight);
-  mozilla::dom::Element* GetTopEnclosingMailCite(nsINode& aNode);
+  Element* GetTopEnclosingMailCite(nsINode& aNode);
   nsresult PopListItem(nsIDOMNode *aListItem, bool *aOutOfList);
-  nsresult RemoveListStructure(nsIDOMNode *aList);
+  nsresult RemoveListStructure(Element& aList);
   nsresult CacheInlineStyles(nsIDOMNode *aNode);
   nsresult ReapplyCachedStyles();
   void ClearCachedStyles();
   void AdjustSpecialBreaks();
-  nsresult AdjustWhitespace(mozilla::dom::Selection* aSelection);
-  nsresult PinSelectionToNewBlock(mozilla::dom::Selection* aSelection);
-  nsresult CheckInterlinePosition(mozilla::dom::Selection* aSelection);
-  nsresult AdjustSelection(mozilla::dom::Selection* aSelection,
+  nsresult AdjustWhitespace(Selection* aSelection);
+  nsresult PinSelectionToNewBlock(Selection* aSelection);
+  void CheckInterlinePosition(Selection& aSelection);
+  nsresult AdjustSelection(Selection* aSelection,
                            nsIEditor::EDirection aAction);
   nsresult FindNearSelectableNode(nsIDOMNode *aSelNode,
                                   int32_t aSelOffset,
                                   nsIEditor::EDirection &aDirection,
                                   nsCOMPtr<nsIDOMNode> *outSelectableNode);
   /**
    * Returns true if aNode1 or aNode2 or both is the descendant of some type of
    * table element, but their nearest table element ancestors differ.  "Table
@@ -332,35 +313,38 @@ protected:
    * table element is its own nearest table element ancestor.
    */
   bool     InDifferentTableElements(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
   bool     InDifferentTableElements(nsINode* aNode1, nsINode* aNode2);
   nsresult RemoveEmptyNodes();
   nsresult SelectionEndpointInNode(nsINode *aNode, bool *aResult);
   nsresult UpdateDocChangeRange(nsRange* aRange);
   nsresult ConfirmSelectionInBody();
-  nsresult InsertMozBRIfNeeded(nsIDOMNode *aNode);
-  bool     IsEmptyInline(nsIDOMNode *aNode);
-  bool     ListIsEmptyLine(nsTArray<mozilla::OwningNonNull<nsINode>>& arrayOfNodes);
+  nsresult InsertMozBRIfNeeded(nsINode& aNode);
+  bool     IsEmptyInline(nsINode& aNode);
+  bool     ListIsEmptyLine(nsTArray<OwningNonNull<nsINode>>& arrayOfNodes);
   nsresult RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignType, bool aChildrenOnly);
   nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, bool aStarts);
-  nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly);
-  nsresult RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, int8_t aRelativeChange);
+  enum class ContentsOnly { no, yes };
+  nsresult AlignBlock(Element& aElement,
+                      const nsAString& aAlignType, ContentsOnly aContentsOnly);
+  enum class Change { minus, plus };
+  nsresult ChangeIndentation(Element& aElement, Change aChange);
   void DocumentModifiedWorker();
 
 // data members
 protected:
   nsHTMLEditor           *mHTMLEditor;
   RefPtr<nsRange>       mDocChangeRange;
   bool                    mListenerEnabled;
   bool                    mReturnInEmptyLIKillsList;
   bool                    mDidDeleteSelection;
   bool                    mDidRangedDelete;
   bool                    mRestoreContentEditableCount;
   RefPtr<nsRange>       mUtilRange;
   uint32_t                mJoinOffset;  // need to remember an int across willJoin/didJoin...
-  nsCOMPtr<nsIDOMNode>    mNewBlock;
+  nsCOMPtr<Element>       mNewBlock;
   RefPtr<nsRangeStore>  mRangeItem;
   StyleCache              mCachedStyles[SIZE_STYLE_TABLE];
 };
 
 #endif //nsHTMLEditRules_h__
 
--- a/editor/libeditor/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/nsHTMLEditUtils.cpp
@@ -254,26 +254,23 @@ bool
 nsHTMLEditUtils::IsTableCell(nsINode* aNode)
 {
   MOZ_ASSERT(aNode);
   return aNode->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
-// IsTableCell: true if node an html td or th
+// IsTableCellOrCaption: true if node an html td or th or caption
 //
 bool
-nsHTMLEditUtils::IsTableCellOrCaption(nsIDOMNode* aNode)
+nsHTMLEditUtils::IsTableCellOrCaption(nsINode& aNode)
 {
-  NS_PRECONDITION(aNode, "null parent passed to nsHTMLEditUtils::IsTableCell");
-  nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aNode);
-  return (nodeAtom == nsGkAtoms::td)
-      || (nodeAtom == nsGkAtoms::th)
-      || (nodeAtom == nsGkAtoms::caption);
+  return aNode.IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th,
+                                   nsGkAtoms::caption);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsList: true if node an html list
 //
 bool
 nsHTMLEditUtils::IsList(nsIDOMNode* aNode)
--- a/editor/libeditor/nsHTMLEditUtils.h
+++ b/editor/libeditor/nsHTMLEditUtils.h
@@ -30,17 +30,17 @@ public:
   static bool IsTable(nsINode* aNode);
   static bool IsTableRow(nsIDOMNode *aNode);
   static bool IsTableElement(nsINode* aNode);
   static bool IsTableElement(nsIDOMNode *aNode);
   static bool IsTableElementButNotTable(nsINode* aNode);
   static bool IsTableElementButNotTable(nsIDOMNode *aNode);
   static bool IsTableCell(nsINode* node);
   static bool IsTableCell(nsIDOMNode *aNode);
-  static bool IsTableCellOrCaption(nsIDOMNode *aNode);
+  static bool IsTableCellOrCaption(nsINode& aNode);
   static bool IsList(nsINode* aNode);
   static bool IsList(nsIDOMNode *aNode);
   static bool IsOrderedList(nsIDOMNode *aNode);
   static bool IsUnorderedList(nsIDOMNode *aNode);
   static bool IsBlockquote(nsIDOMNode *aNode);
   static bool IsPre(nsIDOMNode *aNode);
   static bool IsAnchor(nsIDOMNode *aNode);
   static bool IsImage(nsINode* aNode);
--- a/editor/libeditor/nsHTMLEditor.cpp
+++ b/editor/libeditor/nsHTMLEditor.cpp
@@ -993,24 +993,16 @@ nsHTMLEditor::IsVisBreak(nsINode* aNode)
                         &visOffset, &visType);
   if (visType & WSType::block) {
     return false;
   }
 
   return true;
 }
 
-bool
-nsHTMLEditor::IsVisBreak(nsIDOMNode* aNode)
-{
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  NS_ENSURE_TRUE(node, false);
-  return IsVisBreak(node);
-}
-
 NS_IMETHODIMP
 nsHTMLEditor::GetIsDocumentEditable(bool *aIsDocumentEditable)
 {
   NS_ENSURE_ARG_POINTER(aIsDocumentEditable);
 
   nsCOMPtr<nsIDOMDocument> doc = GetDOMDocument();
   *aIsDocumentEditable = doc && IsModifiable();
 
@@ -1412,17 +1404,17 @@ nsHTMLEditor::RebuildDocumentFromSource(
   // Copy all attributes from the div child to current body element
   CloneAttributes(bodyElement, child->AsElement());
 
   // place selection at first editable content
   return BeginningOfDocument();
 }
 
 void
-nsHTMLEditor::NormalizeEOLInsertPosition(nsIDOMNode *firstNodeToInsert,
+nsHTMLEditor::NormalizeEOLInsertPosition(nsINode* firstNodeToInsert,
                                      nsCOMPtr<nsIDOMNode> *insertParentNode,
                                      int32_t *insertOffset)
 {
   /*
     This function will either correct the position passed in,
     or leave the position unchanged.
 
     When the (first) item to insert is a block level element,
@@ -1492,17 +1484,18 @@ nsHTMLEditor::NormalizeEOLInsertPosition
 NS_IMETHODIMP
 nsHTMLEditor::InsertElementAtSelection(nsIDOMElement* aElement, bool aDeleteSelection)
 {
   // Protect the edit rules object from dying
   nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
 
   nsresult res = NS_ERROR_NOT_INITIALIZED;
 
-  NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
 
   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
 
   ForceCompositionEnd();
   nsAutoEditBatch beginBatching(this);
   nsAutoRules beginRulesSniffing(this, EditAction::insertElement, nsIEditor::eNext);
 
   RefPtr<Selection> selection = GetSelection();
@@ -1516,17 +1509,17 @@ nsHTMLEditor::InsertElementAtSelection(n
   ruleInfo.insertElement = aElement;
   res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
   if (cancel || (NS_FAILED(res))) return res;
 
   if (!handled)
   {
     if (aDeleteSelection)
     {
-      if (!IsBlockNode(aElement)) {
+      if (!IsBlockNode(element)) {
         // E.g., inserting an image.  In this case we don't need to delete any
         // inline wrappers before we do the insertion.  Otherwise we let
         // DeleteSelectionAndPrepareToCreateNode do the deletion for us, which
         // calls DeleteSelection with aStripWrappers = eStrip.
         res = DeleteSelection(nsIEditor::eNone, nsIEditor::eNoStrip);
         NS_ENSURE_SUCCESS(res, res);
       }
 
@@ -1551,17 +1544,18 @@ nsHTMLEditor::InsertElementAtSelection(n
 
     nsCOMPtr<nsIDOMNode> parentSelectedNode;
     int32_t offsetForInsert;
     res = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode));
     // XXX: ERROR_HANDLING bad XPCOM usage
     if (NS_SUCCEEDED(res) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetForInsert)) && parentSelectedNode)
     {
       // Adjust position based on the node we are going to insert.
-      NormalizeEOLInsertPosition(node, address_of(parentSelectedNode), &offsetForInsert);
+      NormalizeEOLInsertPosition(element, address_of(parentSelectedNode),
+                                 &offsetForInsert);
 
       res = InsertNodeAtPoint(node, address_of(parentSelectedNode), &offsetForInsert, false);
       NS_ENSURE_SUCCESS(res, res);
       // Set caret after element, but check for special case
       //  of inserting table-related elements: set in first cell instead
       if (!SetCaretInTableCell(aElement))
       {
         res = SetCaretAfterElement(aElement);
@@ -1652,20 +1646,22 @@ nsHTMLEditor::InsertNodeAtPoint(nsIDOMNo
   // Now we can insert the new node
   res = InsertNode(*node, *parent, *ioOffset);
   return res;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::SelectElement(nsIDOMElement* aElement)
 {
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_STATE(element || !aElement);
   nsresult res = NS_ERROR_NULL_POINTER;
 
   // Must be sure that element is contained in the document body
-  if (IsDescendantOfEditorRoot(aElement)) {
+  if (IsDescendantOfEditorRoot(element)) {
     RefPtr<Selection> selection = GetSelection();
     NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
     nsCOMPtr<nsIDOMNode>parent;
     res = aElement->GetParentNode(getter_AddRefs(parent));
     if (NS_SUCCEEDED(res) && parent)
     {
       int32_t offsetInParent = GetChildOffset(aElement, parent);
 
@@ -1678,20 +1674,22 @@ nsHTMLEditor::SelectElement(nsIDOMElemen
     }
   }
   return res;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
 {
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_STATE(element || !aElement);
   nsresult res = NS_ERROR_NULL_POINTER;
 
   // Be sure the element is contained in the document body
-  if (aElement && IsDescendantOfEditorRoot(aElement)) {
+  if (aElement && IsDescendantOfEditorRoot(element)) {
     RefPtr<Selection> selection = GetSelection();
     NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
     nsCOMPtr<nsIDOMNode>parent;
     res = aElement->GetParentNode(getter_AddRefs(parent));
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
     int32_t offsetInParent = GetChildOffset(aElement, parent);
     // Collapse selection to just after desired element,
@@ -2548,18 +2546,18 @@ nsHTMLEditor::CreateElementWithDefaults(
     realTagName.Assign('a');
   } else {
     realTagName = tagName;
   }
   // We don't use editor's CreateElement because we don't want to go through
   // the transaction system
 
   // New call to use instead to get proper HTML element, bug 39919
-  nsCOMPtr<Element> newElement =
-    CreateHTMLContent(nsCOMPtr<nsIAtom>(NS_Atomize(realTagName)));
+  nsCOMPtr<nsIAtom> realTagAtom = NS_Atomize(realTagName);
+  nsCOMPtr<Element> newElement = CreateHTMLContent(realTagAtom);
   if (!newElement) {
     return nullptr;
   }
 
   // Mark the new element dirty, so it will be formatted
   ErrorResult rv;
   newElement->SetAttribute(NS_LITERAL_STRING("_moz_dirty"), EmptyString(), rv);
 
@@ -3777,105 +3775,89 @@ nsHTMLEditor::SetSelectionAtDocumentStar
 {
   dom::Element* rootElement = GetRoot();
   NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
 
   return aSelection->CollapseNative(rootElement, 0);
 }
 
 
-///////////////////////////////////////////////////////////////////////////
-// RemoveBlockContainer: remove inNode, reparenting its children into their
-//                  the parent of inNode.  In addition, INSERT ANY BR's NEEDED
-//                  TO PRESERVE IDENTITY OF REMOVED BLOCK.
-//
+/**
+ * Remove aNode, reparenting any children into the parent of aNode.  In
+ * addition, insert any br's needed to preserve identity of removed block.
+ */
 nsresult
-nsHTMLEditor::RemoveBlockContainer(nsIDOMNode *inNode)
+nsHTMLEditor::RemoveBlockContainer(nsIContent& aNode)
 {
-  nsCOMPtr<nsIContent> node = do_QueryInterface(inNode);
-  NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-  nsresult res;
-  nsCOMPtr<nsIDOMNode> sibling, child, unused;
-
-  // Two possibilities: the container cold be empty of editable content.
-  // If that is the case, we need to compare what is before and after inNode
-  // to determine if we need a br.
-  // Or it could not be empty, in which case we have to compare previous
-  // sibling and first child to determine if we need a leading br,
-  // and compare following sibling and last child to determine if we need a
-  // trailing br.
-
-  child = GetAsDOMNode(GetFirstEditableChild(*node));
-
-  if (child)  // the case of inNode not being empty
-  {
-    // we need a br at start unless:
-    // 1) previous sibling of inNode is a block, OR
-    // 2) previous sibling of inNode is a br, OR
-    // 3) first child of inNode is a block OR
+  // Two possibilities: the container could be empty of editable content.  If
+  // that is the case, we need to compare what is before and after aNode to
+  // determine if we need a br.
+  //
+  // Or it could be not empty, in which case we have to compare previous
+  // sibling and first child to determine if we need a leading br, and compare
+  // following sibling and last child to determine if we need a trailing br.
+
+  nsCOMPtr<nsIContent> child = GetFirstEditableChild(aNode);
+
+  if (child) {
+    // The case of aNode not being empty.  We need a br at start unless:
+    // 1) previous sibling of aNode is a block, OR
+    // 2) previous sibling of aNode is a br, OR
+    // 3) first child of aNode is a block OR
     // 4) either is null
 
-    res = GetPriorHTMLSibling(inNode, address_of(sibling));
-    NS_ENSURE_SUCCESS(res, res);
-    if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
-    {
-      if (!IsBlockNode(child)) {
-        // insert br node
-        res = CreateBR(inNode, 0, address_of(unused));
-        NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<nsIContent> sibling = GetPriorHTMLSibling(&aNode);
+    if (sibling && !IsBlockNode(sibling) &&
+        !sibling->IsHTMLElement(nsGkAtoms::br) && !IsBlockNode(child)) {
+      // Insert br node
+      nsCOMPtr<Element> br = CreateBR(&aNode, 0);
+      NS_ENSURE_STATE(br);
+    }
+
+    // We need a br at end unless:
+    // 1) following sibling of aNode is a block, OR
+    // 2) last child of aNode is a block, OR
+    // 3) last child of aNode is a br OR
+    // 4) either is null
+
+    sibling = GetNextHTMLSibling(&aNode);
+    if (sibling && !IsBlockNode(sibling)) {
+      child = GetLastEditableChild(aNode);
+      MOZ_ASSERT(child, "aNode has first editable child but not last?");
+      if (!IsBlockNode(child) && !child->IsHTMLElement(nsGkAtoms::br)) {
+        // Insert br node
+        nsCOMPtr<Element> br = CreateBR(&aNode, aNode.Length());
+        NS_ENSURE_STATE(br);
       }
     }
-
-    // we need a br at end unless:
-    // 1) following sibling of inNode is a block, OR
-    // 2) last child of inNode is a block, OR
-    // 3) last child of inNode is a block OR
-    // 4) either is null
-
-    res = GetNextHTMLSibling(inNode, address_of(sibling));
-    NS_ENSURE_SUCCESS(res, res);
-    if (sibling && !IsBlockNode(sibling))
-    {
-      child = GetAsDOMNode(GetLastEditableChild(*node));
-      if (child && !IsBlockNode(child) && !nsTextEditUtils::IsBreak(child))
-      {
-        // insert br node
-        uint32_t len;
-        res = GetLengthOfDOMNode(inNode, len);
-        NS_ENSURE_SUCCESS(res, res);
-        res = CreateBR(inNode, (int32_t)len, address_of(unused));
-        NS_ENSURE_SUCCESS(res, res);
+  } else {
+    // The case of aNode being empty.  We need a br at start unless:
+    // 1) previous sibling of aNode is a block, OR
+    // 2) previous sibling of aNode is a br, OR
+    // 3) following sibling of aNode is a block, OR
+    // 4) following sibling of aNode is a br OR
+    // 5) either is null
+    nsCOMPtr<nsIContent> sibling = GetPriorHTMLSibling(&aNode);
+    if (sibling && !IsBlockNode(sibling) &&
+        !sibling->IsHTMLElement(nsGkAtoms::br)) {
+      sibling = GetNextHTMLSibling(&aNode);
+      if (sibling && !IsBlockNode(sibling) &&
+          !sibling->IsHTMLElement(nsGkAtoms::br)) {
+        // Insert br node
+        nsCOMPtr<Element> br = CreateBR(&aNode, 0);
+        NS_ENSURE_STATE(br);
       }
     }
   }
-  else  // the case of inNode being empty
-  {
-    // we need a br at start unless:
-    // 1) previous sibling of inNode is a block, OR
-    // 2) previous sibling of inNode is a br, OR
-    // 3) following sibling of inNode is a block, OR
-    // 4) following sibling of inNode is a br OR
-    // 5) either is null
-    res = GetPriorHTMLSibling(inNode, address_of(sibling));
-    NS_ENSURE_SUCCESS(res, res);
-    if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
-    {
-      res = GetNextHTMLSibling(inNode, address_of(sibling));
-      NS_ENSURE_SUCCESS(res, res);
-      if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
-      {
-        // insert br node
-        res = CreateBR(inNode, 0, address_of(unused));
-        NS_ENSURE_SUCCESS(res, res);
-      }
-    }
-  }
-
-  // now remove container
-  return RemoveContainer(node);
+
+  // Now remove container
+  nsresult res = RemoveContainer(&aNode);
+  NS_ENSURE_SUCCESS(res, res);
+
+  return NS_OK;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // GetPriorHTMLSibling: returns the previous editable sibling, if there is
 //                   one within the parent
 //
 nsIContent*
@@ -4714,17 +4696,17 @@ nsHTMLEditor::AreNodesSameType(nsIConten
 
   // If CSS is enabled, we are stricter about span nodes.
   return mHTMLCSSUtils->ElementsSameStyle(aNode1->AsDOMNode(),
                                           aNode2->AsDOMNode());
 }
 
 nsresult
 nsHTMLEditor::CopyLastEditableChildStyles(nsIDOMNode * aPreviousBlock, nsIDOMNode * aNewBlock,
-                                          nsIDOMNode **aOutBrNode)
+                                          Element** aOutBrNode)
 {
   nsCOMPtr<nsINode> newBlock = do_QueryInterface(aNewBlock);
   NS_ENSURE_STATE(newBlock || !aNewBlock);
   *aOutBrNode = nullptr;
   nsCOMPtr<nsIDOMNode> child, tmp;
   nsresult res;
   // first, clear out aNewBlock.  Contract is that we want only the styles from previousBlock.
   res = aNewBlock->GetFirstChild(getter_AddRefs(child));
@@ -4768,17 +4750,17 @@ nsHTMLEditor::CopyLastEditableChildStyle
           CreateNode(childElement->NodeInfo()->NameAtom(), newBlock, 0);
         NS_ENSURE_STATE(newStyles);
       }
       CloneAttributes(newStyles, childElement);
     }
     childElement = childElement->GetParentElement();
   }
   if (deepestStyle) {
-    *aOutBrNode = GetAsDOMNode(CreateBR(deepestStyle, 0));
+    *aOutBrNode = CreateBR(deepestStyle, 0);
     NS_ENSURE_STATE(*aOutBrNode);
   }
   return NS_OK;
 }
 
 nsresult
 nsHTMLEditor::GetElementOrigin(nsIDOMElement * aElement, int32_t & aX, int32_t & aY)
 {
@@ -4818,99 +4800,84 @@ nsHTMLEditor::EndUpdateViewBatch()
     RefPtr<Selection> selection = GetSelection();
     NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
     res = CheckSelectionStateForAnonymousButtons(selection);
   }
   return res;
 }
 
 NS_IMETHODIMP
-nsHTMLEditor::GetSelectionContainer(nsIDOMElement ** aReturn)
+nsHTMLEditor::GetSelectionContainer(nsIDOMElement** aReturn)
+{
+  nsCOMPtr<nsIDOMElement> container =
+    static_cast<nsIDOMElement*>(GetAsDOMNode(GetSelectionContainer()));
+  NS_ENSURE_TRUE(container, NS_ERROR_FAILURE);
+  container.forget(aReturn);
+  return NS_OK;
+}
+
+Element*
+nsHTMLEditor::GetSelectionContainer()
 {
-  RefPtr<Selection> selection = GetSelection();
-  // if we don't get the selection, just skip this
-  if (!selection) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIDOMNode> focusNode;
-
-  nsresult res;
+  // If we don't get the selection, just skip this
+  NS_ENSURE_TRUE(GetSelection(), nullptr);
+
+  OwningNonNull<Selection> selection = *GetSelection();
+
+  nsCOMPtr<nsINode> focusNode;
+
   if (selection->Collapsed()) {
-    res = selection->GetFocusNode(getter_AddRefs(focusNode));
-    NS_ENSURE_SUCCESS(res, res);
+    focusNode = selection->GetFocusNode();
   } else {
-
-    int32_t rangeCount;
-    res = selection->GetRangeCount(&rangeCount);
-    NS_ENSURE_SUCCESS(res, res);
+    int32_t rangeCount = selection->RangeCount();
 
     if (rangeCount == 1) {
-
       RefPtr<nsRange> range = selection->GetRangeAt(0);
-      NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
-
-      nsCOMPtr<nsIDOMNode> startContainer, endContainer;
-      res = range->GetStartContainer(getter_AddRefs(startContainer));
-      NS_ENSURE_SUCCESS(res, res);
-      res = range->GetEndContainer(getter_AddRefs(endContainer));
-      NS_ENSURE_SUCCESS(res, res);
-      int32_t startOffset, endOffset;
-      res = range->GetStartOffset(&startOffset);
-      NS_ENSURE_SUCCESS(res, res);
-      res = range->GetEndOffset(&endOffset);
-      NS_ENSURE_SUCCESS(res, res);
-
-      nsCOMPtr<nsIDOMElement> focusElement;
+
+      nsCOMPtr<nsINode> startContainer = range->GetStartParent();
+      int32_t startOffset = range->StartOffset();
+      nsCOMPtr<nsINode> endContainer = range->GetEndParent();
+      int32_t endOffset = range->EndOffset();
+
       if (startContainer == endContainer && startOffset + 1 == endOffset) {
-        res = GetSelectedElement(EmptyString(), getter_AddRefs(focusElement));
-        NS_ENSURE_SUCCESS(res, res);
-        if (focusElement)
+        nsCOMPtr<nsIDOMElement> focusElement;
+        nsresult res = GetSelectedElement(EmptyString(),
+                                          getter_AddRefs(focusElement));
+        NS_ENSURE_SUCCESS(res, nullptr);
+        if (focusElement) {
           focusNode = do_QueryInterface(focusElement);
+        }
       }
       if (!focusNode) {
-        res = range->GetCommonAncestorContainer(getter_AddRefs(focusNode));
-        NS_ENSURE_SUCCESS(res, res);
+        focusNode = range->GetCommonAncestor();
       }
-    }
-    else {
-      int32_t i;
-      RefPtr<nsRange> range;
-      for (i = 0; i < rangeCount; i++)
-      {
-        range = selection->GetRangeAt(i);
-        NS_ENSURE_STATE(range);
-        nsCOMPtr<nsIDOMNode> startContainer;
-        res = range->GetStartContainer(getter_AddRefs(startContainer));
-        if (NS_FAILED(res)) continue;
-        if (!focusNode)
+    } else {
+      for (int32_t i = 0; i < rangeCount; i++) {
+        RefPtr<nsRange> range = selection->GetRangeAt(i);
+
+        nsCOMPtr<nsINode> startContainer = range->GetStartParent();
+        if (!focusNode) {
           focusNode = startContainer;
-        else if (focusNode != startContainer) {
-          res = startContainer->GetParentNode(getter_AddRefs(focusNode));
-          NS_ENSURE_SUCCESS(res, res);
+        } else if (focusNode != startContainer) {
+          focusNode = startContainer->GetParentNode();
           break;
         }
       }
     }
   }
 
-  if (focusNode) {
-    uint16_t nodeType;
-    focusNode->GetNodeType(&nodeType);
-    if (nsIDOMNode::TEXT_NODE == nodeType) {
-      nsCOMPtr<nsIDOMNode> parent;
-      res = focusNode->GetParentNode(getter_AddRefs(parent));
-      NS_ENSURE_SUCCESS(res, res);
-      focusNode = parent;
-    }
-  }
-
-  nsCOMPtr<nsIDOMElement> focusElement = do_QueryInterface(focusNode);
-  focusElement.forget(aReturn);
-  return NS_OK;
+  if (focusNode && focusNode->GetAsText()) {
+    focusNode = focusNode->GetParentNode();
+  }
+
+  if (focusNode && focusNode->IsElement()) {
+    return focusNode->AsElement();
+  }
+
+  return nullptr;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::IsAnonymousElement(nsIDOMElement * aElement, bool * aReturn)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
   *aReturn = content->IsRootOfNativeAnonymousSubtree();
--- a/editor/libeditor/nsHTMLEditor.h
+++ b/editor/libeditor/nsHTMLEditor.h
@@ -96,26 +96,27 @@ public:
 // another class. Only the base class should use NS_DECL_ISUPPORTS
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLEditor, nsPlaintextEditor)
 
 
   nsHTMLEditor();
 
   bool GetReturnInParagraphCreatesNewParagraph();
+  Element* GetSelectionContainer();
 
   /* ------------ nsPlaintextEditor overrides -------------- */
   NS_IMETHOD GetIsDocumentEditable(bool *aIsDocumentEditable) override;
   NS_IMETHOD BeginningOfDocument() override;
   virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) override;
   virtual already_AddRefed<nsIContent> GetFocusedContent() override;
   virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
   virtual bool IsActiveInDOMWindow() override;
   virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() override;
-  virtual mozilla::dom::Element* GetEditorRoot() override;
+  virtual Element* GetEditorRoot() override;
   virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode *aNode) override;
   virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent) override;
   virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
   virtual bool IsEditable(nsINode* aNode) override;
   using nsEditor::IsEditable;
 
   /* ------------ nsStubMutationObserver overrides --------- */
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
@@ -138,17 +139,17 @@ public:
   NS_DECL_NSIHTMLABSPOSEDITOR
 
   /* ------------ nsIHTMLInlineTableEditor methods -------------- */
   /* ------- Implemented in nsHTMLInlineTableEditor.cpp --------- */
   NS_DECL_NSIHTMLINLINETABLEEDITOR
 
   /* ------------ nsIHTMLEditor methods -------------- */
   nsresult CopyLastEditableChildStyles(nsIDOMNode *aPreviousBlock, nsIDOMNode *aNewBlock,
-                                         nsIDOMNode **aOutBrNode);
+                                       Element** aOutBrNode);
 
   nsresult LoadHTML(const nsAString &aInputString);
 
   nsresult GetCSSBackgroundColorState(bool *aMixed, nsAString &aOutColor,
                                       bool aBlockLevel);
   NS_IMETHOD GetHTMLBackgroundColorState(bool *aMixed, nsAString &outColor);
 
   /* ------------ nsIEditorStyleSheets methods -------------- */
@@ -227,19 +228,19 @@ public:
 
   /* miscellaneous */
   // This sets background on the appropriate container element (table, cell,)
   //   or calls into nsTextEditor to set the page background
   nsresult SetCSSBackgroundColor(const nsAString& aColor);
   nsresult SetHTMLBackgroundColor(const nsAString& aColor);
 
   /* ------------ Block methods moved from nsEditor -------------- */
-  static mozilla::dom::Element* GetBlockNodeParent(nsINode* aNode);
+  static Element* GetBlockNodeParent(nsINode* aNode);
   static nsIDOMNode* GetBlockNodeParent(nsIDOMNode* aNode);
-  static mozilla::dom::Element* GetBlock(nsINode& aNode);
+  static Element* GetBlock(nsINode& aNode);
 
   void IsNextCharInNodeWhitespace(nsIContent* aContent,
                                   int32_t aOffset,
                                   bool* outIsSpace,
                                   bool* outIsNBSP,
                                   nsIContent** outNode = nullptr,
                                   int32_t* outOffset = 0);
   void IsPrevCharInNodeWhitespace(nsIContent* aContent,
@@ -293,17 +294,17 @@ public:
   virtual bool TagCanContainTag(nsIAtom& aParentTag, nsIAtom& aChildTag)
     override;
 
   /** returns true if aNode is a container */
   virtual bool IsContainer(nsINode* aNode) override;
   virtual bool IsContainer(nsIDOMNode* aNode) override;
 
   /** make the given selection span the entire document */
-  virtual nsresult SelectEntireDocument(mozilla::dom::Selection* aSelection) override;
+  virtual nsresult SelectEntireDocument(Selection* aSelection) override;
 
   NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement * aElement,
                                       const nsAString & aAttribute,
                                       const nsAString & aValue,
                                       bool aSuppressTransaction) override;
   NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement * aElement,
                                          const nsAString & aAttribute,
                                          bool aSuppressTransaction) override;
@@ -345,18 +346,18 @@ public:
                               bool aNoEmptyNodes);
 
   // Use this to assure that selection is set after attribute nodes when
   //  trying to collapse selection at begining of a block node
   //  e.g., when setting at beginning of a table cell
   // This will stop at a table, however, since we don't want to
   //  "drill down" into nested tables.
   // aSelection is optional -- if null, we get current seletion
-  void CollapseSelectionToDeepestNonTableFirstChild(
-                          mozilla::dom::Selection* aSelection, nsINode* aNode);
+  void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
+                                                    nsINode* aNode);
 
   /**
    * aNode must be a non-null text node.
    * outIsEmptyNode must be non-null.
    */
   nsresult IsVisTextNode(nsIContent* aNode,
                          bool* outIsEmptyNode,
                          bool aSafeToAskFrames);
@@ -390,17 +391,17 @@ public:
   nsresult RemoveStyleSheetFromList(const nsAString &aURL);
 
   bool IsCSSEnabled()
   {
     // TODO: removal of mCSSAware and use only the presence of mHTMLCSSUtils
     return mCSSAware && mHTMLCSSUtils && mHTMLCSSUtils->IsCSSPrefChecked();
   }
 
-  static bool HasAttributes(mozilla::dom::Element* aElement)
+  static bool HasAttributes(Element* aElement)
   {
     MOZ_ASSERT(aElement);
     uint32_t attrCount = aElement->GetAttrCount();
     return attrCount > 1 ||
            (1 == attrCount && !aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty));
   }
 
 protected:
@@ -421,18 +422,18 @@ protected:
   //            Otherwise, returns null.
   already_AddRefed<nsINode> GetFocusedNode();
 
   // Return TRUE if aElement is a table-related elemet and caret was set
   bool SetCaretInTableCell(nsIDOMElement* aElement);
 
   // key event helpers
   NS_IMETHOD TabInTable(bool inIsShift, bool *outHandled);
-  mozilla::dom::Element* CreateBR(nsINode* aNode, int32_t aOffset,
-                                  EDirection aSelect = eNone);
+  Element* CreateBR(nsINode* aNode, int32_t aOffset,
+                    EDirection aSelect = eNone);
   NS_IMETHOD CreateBR(nsIDOMNode *aNode, int32_t aOffset,
                       nsCOMPtr<nsIDOMNode> *outBRNode, nsIEditor::EDirection aSelect = nsIEditor::eNone) override;
 
 // Table Editing (implemented in nsTableEditor.cpp)
 
   // Table utilities
 
   // Insert a new cell after or before supplied aCell.
@@ -444,41 +445,40 @@ protected:
   // Helpers that don't touch the selection or do batch transactions
   NS_IMETHOD DeleteRow(nsIDOMElement *aTable, int32_t aRowIndex);
   NS_IMETHOD DeleteColumn(nsIDOMElement *aTable, int32_t aColIndex);
   NS_IMETHOD DeleteCellContents(nsIDOMElement *aCell);
 
   // Move all contents from aCellToMerge into aTargetCell (append at end)
   NS_IMETHOD MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell, nsCOMPtr<nsIDOMElement> aCellToMerge, bool aDeleteCellToMerge);
 
-  nsresult DeleteTable2(nsIDOMElement* aTable,
-                        mozilla::dom::Selection* aSelection);
+  nsresult DeleteTable2(nsIDOMElement* aTable, Selection* aSelection);
   NS_IMETHOD SetColSpan(nsIDOMElement *aCell, int32_t aColSpan);
   NS_IMETHOD SetRowSpan(nsIDOMElement *aCell, int32_t aRowSpan);
 
   // Helper used to get nsTableOuterFrame for a table.
   nsTableOuterFrame* GetTableFrame(nsIDOMElement* aTable);
   // Needed to do appropriate deleting when last cell or row is about to be deleted
   // This doesn't count cells that don't start in the given row (are spanning from row above)
   int32_t  GetNumberOfCellsInRow(nsIDOMElement* aTable, int32_t rowIndex);
   // Test if all cells in row or column at given index are selected
   bool AllCellsInRowSelected(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aNumberOfColumns);
   bool AllCellsInColumnSelected(nsIDOMElement *aTable, int32_t aColIndex, int32_t aNumberOfRows);
 
-  bool IsEmptyCell(mozilla::dom::Element* aCell);
+  bool IsEmptyCell(Element* aCell);
 
   // Most insert methods need to get the same basic context data
   // Any of the pointers may be null if you don't need that datum (for more efficiency)
   // Input: *aCell is a known cell,
   //        if null, cell is obtained from the anchor node of the selection
   // Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is null
-  nsresult GetCellContext(mozilla::dom::Selection** aSelection,
-                          nsIDOMElement** aTable, nsIDOMElement** aCell,
-                          nsIDOMNode** aCellParent, int32_t* aCellOffset,
-                          int32_t* aRowIndex, int32_t* aColIndex);
+  nsresult GetCellContext(Selection** aSelection, nsIDOMElement** aTable,
+                          nsIDOMElement** aCell, nsIDOMNode** aCellParent,
+                          int32_t* aCellOffset, int32_t* aRowIndex,
+                          int32_t* aColIndex);
 
   NS_IMETHOD GetCellSpansAt(nsIDOMElement* aTable, int32_t aRowIndex, int32_t aColIndex,
                             int32_t& aActualRowSpan, int32_t& aActualColSpan);
 
   NS_IMETHOD SplitCellIntoColumns(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aColIndex,
                                   int32_t aColSpanLeft, int32_t aColSpanRight, nsIDOMElement **aNewCell);
 
   NS_IMETHOD SplitCellIntoRows(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aColIndex,
@@ -487,21 +487,21 @@ protected:
   nsresult CopyCellBackgroundColor(nsIDOMElement *destCell, nsIDOMElement *sourceCell);
 
   // Reduce rowspan/colspan when cells span into nonexistent rows/columns
   NS_IMETHOD FixBadRowSpan(nsIDOMElement *aTable, int32_t aRowIndex, int32_t& aNewRowCount);
   NS_IMETHOD FixBadColSpan(nsIDOMElement *aTable, int32_t aColIndex, int32_t& aNewColCount);
 
   // Fallback method: Call this after using ClearSelection() and you
   //  failed to set selection to some other content in the document
-  nsresult SetSelectionAtDocumentStart(mozilla::dom::Selection* aSelection);
+  nsresult SetSelectionAtDocumentStart(Selection* aSelection);
 
 // End of Table Editing utilities
 
-  static mozilla::dom::Element* GetEnclosingTable(nsINode* aNode);
+  static Element* GetEnclosingTable(nsINode* aNode);
   static nsIDOMNode* GetEnclosingTable(nsIDOMNode *aNode);
 
   /** content-based query returns true if <aProperty aAttribute=aValue> effects aNode
     * If <aProperty aAttribute=aValue> contains aNode,
     * but <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
     * more deeply nested than the first, then the first does not effect aNode.
     *
     * @param aNode      The target of the query
@@ -592,109 +592,101 @@ protected:
                                         int32_t *outStartOffset,
                                         int32_t *outEndOffset,
                                         bool aTrustedInput);
   nsresult   ParseFragment(const nsAString & aStr, nsIAtom* aContextLocalName,
                            nsIDocument* aTargetDoc,
                            mozilla::dom::DocumentFragment** aFragment,
                            bool aTrustedInput);
   void       CreateListOfNodesToPaste(mozilla::dom::DocumentFragment& aFragment,
-                                      nsTArray<mozilla::OwningNonNull<nsINode>>& outNodeList,
+                                      nsTArray<OwningNonNull<nsINode>>& outNodeList,
                                       nsINode* aStartNode,
                                       int32_t aStartOffset,
                                       nsINode* aEndNode,
                                       int32_t aEndOffset);
   nsresult CreateTagStack(nsTArray<nsString> &aTagStack,
                           nsIDOMNode *aNode);
   enum class StartOrEnd { start, end };
   void GetListAndTableParents(StartOrEnd aStartOrEnd,
-                              nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeList,
-                              nsTArray<mozilla::OwningNonNull<mozilla::dom::Element>>& outArray);
-  int32_t DiscoverPartialListsAndTables(nsTArray<mozilla::OwningNonNull<nsINode>>& aPasteNodes,
-                                        nsTArray<mozilla::OwningNonNull<mozilla::dom::Element>>& aListsAndTables);
+                              nsTArray<OwningNonNull<nsINode>>& aNodeList,
+                              nsTArray<OwningNonNull<Element>>& outArray);
+  int32_t DiscoverPartialListsAndTables(nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
+                                        nsTArray<OwningNonNull<Element>>& aListsAndTables);
   nsINode* ScanForListAndTableStructure(StartOrEnd aStartOrEnd,
-                                        nsTArray<mozilla::OwningNonNull<nsINode>>& aNodes,
-                                        mozilla::dom::Element& aListOrTable);
+                                        nsTArray<OwningNonNull<nsINode>>& aNodes,
+                                        Element& aListOrTable);
   void ReplaceOrphanedStructure(StartOrEnd aStartOrEnd,
-                                nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeArray,
-                                nsTArray<mozilla::OwningNonNull<mozilla::dom::Element>>& aListAndTableArray,
+                                nsTArray<OwningNonNull<nsINode>>& aNodeArray,
+                                nsTArray<OwningNonNull<Element>>& aListAndTableArray,
                                 int32_t aHighWaterMark);
 
   /* small utility routine to test if a break node is visible to user */
   bool     IsVisBreak(nsINode* aNode);
-  bool     IsVisBreak(nsIDOMNode *aNode);
 
   /* utility routine to possibly adjust the insertion position when
      inserting a block level element */
-  void NormalizeEOLInsertPosition(nsIDOMNode *firstNodeToInsert,
+  void NormalizeEOLInsertPosition(nsINode* firstNodeToInsert,
                                   nsCOMPtr<nsIDOMNode> *insertParentNode,
                                   int32_t *insertOffset);
 
   /* small utility routine to test the eEditorReadonly bit */
   bool IsModifiable();
 
   /* helpers for block transformations */
   nsresult MakeDefinitionItem(const nsAString & aItemType);
   nsresult InsertBasicBlock(const nsAString & aBlockType);
 
   /* increase/decrease the font size of selection */
   enum class FontSize { incr, decr };
   nsresult RelativeFontChange(FontSize aDir);
 
   /* helper routines for font size changing */
-  nsresult RelativeFontChangeOnTextNode( int32_t aSizeChange,
-                                         nsIDOMCharacterData *aTextNode,
-                                         int32_t aStartOffset,
-                                         int32_t aEndOffset);
+  nsresult RelativeFontChangeOnTextNode(FontSize aDir,
+                                        Text& aTextNode,
+                                        int32_t aStartOffset,
+                                        int32_t aEndOffset);
   nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
   nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
 
   /* helper routines for inline style */
-  nsresult SetInlinePropertyOnTextNode(mozilla::dom::Text& aData,
+  nsresult SetInlinePropertyOnTextNode(Text& aData,
                                        int32_t aStartOffset,
                                        int32_t aEndOffset,
                                        nsIAtom& aProperty,
                                        const nsAString* aAttribute,
                                        const nsAString& aValue);
   nsresult SetInlinePropertyOnNode(nsIContent& aNode,
                                    nsIAtom& aProperty,
                                    const nsAString* aAttribute,
                                    const nsAString& aValue);
 
-  nsresult PromoteInlineRange(nsRange* aRange);
-  nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange* aRange);
+  nsresult PromoteInlineRange(nsRange& aRange);
+  nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
   nsresult SplitStyleAboveRange(nsRange* aRange,
                                 nsIAtom *aProperty,
                                 const nsAString *aAttribute);
-  nsresult SplitStyleAbovePoint(nsCOMPtr<nsIDOMNode> *aNode,
-                                int32_t *aOffset,
-                                nsIAtom *aProperty,
-                                const nsAString *aAttribute,
-                                nsCOMPtr<nsIDOMNode> *outLeftNode = nullptr,
-                                nsCOMPtr<nsIDOMNode> *outRightNode = nullptr);
+  nsresult SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
+                                nsIAtom* aProperty,
+                                const nsAString* aAttribute,
+                                nsIContent** aOutLeftNode = nullptr,
+                                nsIContent** aOutRightNode = nullptr);
   nsresult ApplyDefaultProperties();
-  nsresult RemoveStyleInside(nsIDOMNode *aNode,
-                             nsIAtom *aProperty,
-                             const nsAString *aAttribute,
-                             const bool aChildrenOnly = false);
   nsresult RemoveStyleInside(nsIContent& aNode,
                              nsIAtom* aProperty,
                              const nsAString* aAttribute,
                              const bool aChildrenOnly = false);
   nsresult RemoveInlinePropertyImpl(nsIAtom* aProperty,
                                     const nsAString* aAttribute);
 
-  bool NodeIsProperty(nsIDOMNode *aNode);
-  bool HasAttr(nsIDOMNode *aNode, const nsAString *aAttribute);
-  bool IsAtFrontOfNode(nsIDOMNode *aNode, int32_t aOffset);
-  bool IsAtEndOfNode(nsIDOMNode *aNode, int32_t aOffset);
-  bool IsOnlyAttribute(nsIDOMNode *aElement, const nsAString *aAttribute);
+  bool NodeIsProperty(nsINode& aNode);
+  bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset);
+  bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset);
   bool IsOnlyAttribute(const nsIContent* aElement, const nsAString& aAttribute);
 
-  nsresult RemoveBlockContainer(nsIDOMNode *inNode);
+  nsresult RemoveBlockContainer(nsIContent& aNode);
 
   nsIContent* GetPriorHTMLSibling(nsINode* aNode);
   nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
   nsIContent* GetPriorHTMLSibling(nsINode* aParent, int32_t aOffset);
   nsresult GetPriorHTMLSibling(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr<nsIDOMNode> *outNode);
 
   nsIContent* GetNextHTMLSibling(nsINode* aNode);
   nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
@@ -724,18 +716,18 @@ protected:
   nsresult GetInlinePropertyBase(nsIAtom& aProperty,
                                  const nsAString* aAttribute,
                                  const nsAString* aValue,
                                  bool* aFirst,
                                  bool* aAny,
                                  bool* aAll,
                                  nsAString* outValue,
                                  bool aCheckDefaults = true);
-  bool HasStyleOrIdOrClass(mozilla::dom::Element* aElement);
-  nsresult RemoveElementIfNoStyleOrIdOrClass(mozilla::dom::Element& aElement);
+  bool HasStyleOrIdOrClass(Element* aElement);
+  nsresult RemoveElementIfNoStyleOrIdOrClass(Element& aElement);
 
   // Whether the outer window of the DOM event target has focus or not.
   bool     OurWindowHasFocus();
 
   // This function is used to insert a string of HTML input optionally with some
   // context information into the editable field.  The HTML input either comes
   // from a transferable object created as part of a drop/paste operation, or from
   // the InsertHTML method.  We may want the HTML input to be sanitized (for example,
@@ -751,26 +743,25 @@ protected:
                                    const nsAString& aFlavor,
                                    nsIDOMDocument* aSourceDoc,
                                    nsIDOMNode* aDestNode,
                                    int32_t aDestOffset,
                                    bool aDeleteSelection,
                                    bool aTrustedInput,
                                    bool aClearStyle = true);
 
-  nsresult ClearStyle(nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset,
+  nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
                       nsIAtom* aProperty, const nsAString* aAttribute);
 
-  void SetElementPosition(mozilla::dom::Element& aElement,
-                          int32_t aX, int32_t aY);
+  void SetElementPosition(Element& aElement, int32_t aX, int32_t aY);
 
 // Data members
 protected:
 
-  nsTArray<mozilla::OwningNonNull<nsIContentFilter>> mContentFilters;
+  nsTArray<OwningNonNull<nsIContentFilter>> mContentFilters;
 
   RefPtr<TypeInState>        mTypeInState;
 
   bool mCRInParagraphCreatesParagraph;
 
   bool mCSSAware;
   nsAutoPtr<nsHTMLCSSUtils> mHTMLCSSUtils;
 
@@ -788,17 +779,17 @@ protected:
   nsTArray<PropItem*> mDefaultStyles;
 
 protected:
 
   /* ANONYMOUS UTILS */
   void     RemoveListenerAndDeleteRef(const nsAString& aEvent,
                                       nsIDOMEventListener* aListener,
                                       bool aUseCapture,
-                                      mozilla::dom::Element* aElement,
+                                      Element* aElement,
                                       nsIContent* aParentContent,
                                       nsIPresShell* aShell);
   void     DeleteRefToAnonymousNode(nsIDOMElement* aElement,
                                     nsIContent * aParentContent,
                                     nsIPresShell* aShell);
 
   nsresult ShowResizersInner(nsIDOMElement *aResizedElement);
 
@@ -830,37 +821,37 @@ protected:
 
   bool mSnapToGridEnabled;
 
   // inline table editing
   bool mIsInlineTableEditingEnabled;
 
   /* RESIZING */
 
-  nsCOMPtr<mozilla::dom::Element> mTopLeftHandle;
-  nsCOMPtr<mozilla::dom::Element> mTopHandle;
-  nsCOMPtr<mozilla::dom::Element> mTopRightHandle;
-  nsCOMPtr<mozilla::dom::Element> mLeftHandle;
-  nsCOMPtr<mozilla::dom::Element> mRightHandle;
-  nsCOMPtr<mozilla::dom::Element> mBottomLeftHandle;
-  nsCOMPtr<mozilla::dom::Element> mBottomHandle;
-  nsCOMPtr<mozilla::dom::Element> mBottomRightHandle;
+  nsCOMPtr<Element> mTopLeftHandle;
+  nsCOMPtr<Element> mTopHandle;
+  nsCOMPtr<Element> mTopRightHandle;
+  nsCOMPtr<Element> mLeftHandle;
+  nsCOMPtr<Element> mRightHandle;
+  nsCOMPtr<Element> mBottomLeftHandle;
+  nsCOMPtr<Element> mBottomHandle;
+  nsCOMPtr<Element> mBottomRightHandle;
 
-  nsCOMPtr<mozilla::dom::Element> mActivatedHandle;
+  nsCOMPtr<Element> mActivatedHandle;
 
-  nsCOMPtr<mozilla::dom::Element> mResizingShadow;
-  nsCOMPtr<mozilla::dom::Element> mResizingInfo;
+  nsCOMPtr<Element> mResizingShadow;
+  nsCOMPtr<Element> mResizingInfo;
 
-  nsCOMPtr<mozilla::dom::Element> mResizedObject;
+  nsCOMPtr<Element> mResizedObject;
 
   nsCOMPtr<nsIDOMEventListener>  mMouseMotionListenerP;
   nsCOMPtr<nsISelectionListener> mSelectionListenerP;
   nsCOMPtr<nsIDOMEventListener>  mResizeEventListenerP;
 
-  nsTArray<mozilla::OwningNonNull<nsIHTMLObjectResizeListener>> mObjectResizeEventListeners;
+  nsTArray<OwningNonNull<nsIHTMLObjectResizeListener>> mObjectResizeEventListeners;
 
   int32_t mOriginalX;
   int32_t mOriginalY;
 
   int32_t mResizedObjectX;
   int32_t mResizedObjectY;
   int32_t mResizedObjectWidth;
   int32_t mResizedObjectHeight;
@@ -875,28 +866,27 @@ protected:
   int32_t mWidthIncrementFactor;
   int32_t mHeightIncrementFactor;
 
   int8_t  mInfoXIncrement;
   int8_t  mInfoYIncrement;
 
   nsresult SetAllResizersPosition();
 
-  already_AddRefed<mozilla::dom::Element>
-    CreateResizer(int16_t aLocation, nsIDOMNode* aParentNode);
+  already_AddRefed<Element> CreateResizer(int16_t aLocation,
+                                          nsIDOMNode* aParentNode);
   void     SetAnonymousElementPosition(int32_t aX, int32_t aY, nsIDOMElement *aResizer);
 
-  already_AddRefed<mozilla::dom::Element>
-    CreateShadow(nsIDOMNode* aParentNode, nsIDOMElement* aOriginalObject);
-  nsresult SetShadowPosition(mozilla::dom::Element* aShadow,
-                             mozilla::dom::Element* aOriginalObject,
+  already_AddRefed<Element> CreateShadow(nsIDOMNode* aParentNode,
+                                         nsIDOMElement* aOriginalObject);
+  nsresult SetShadowPosition(Element* aShadow, Element* aOriginalObject,
                              int32_t aOriginalObjectX,
                              int32_t aOriginalObjectY);
 
-  already_AddRefed<