Merge inbound to mozilla-central r=merge a=merge
authorDorel Luca <dluca@mozilla.com>
Thu, 07 Dec 2017 00:01:19 +0200
changeset 449619 99a3b09ac1898eb1db05430e2876d6643ba0d4a8
parent 449539 155c25df7f182c58baa2d493aa5c056f14c724c6 (current diff)
parent 449618 d9ec1dda6c57b28b460a3e5bc35451519854593b (diff)
child 449620 4b94da21a9e6171f9911ffad171af23c26e6227b
child 449647 f19a94ec336a442baf631c7e325b605225c710b6
child 449700 a7c469000c39b05fa4740dd36546018cbbe2f66c
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.0a1
first release with
nightly linux32
99a3b09ac189 / 59.0a1 / 20171206221407 / files
nightly linux64
99a3b09ac189 / 59.0a1 / 20171206221407 / files
nightly mac
99a3b09ac189 / 59.0a1 / 20171206221407 / files
nightly win32
99a3b09ac189 / 59.0a1 / 20171206221407 / files
nightly win64
99a3b09ac189 / 59.0a1 / 20171206221407 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central r=merge a=merge
accessible/base/ARIAMap.cpp
accessible/base/ARIAMap.h
accessible/base/nsAccessibilityService.cpp
accessible/generic/ARIAGridAccessible.cpp
accessible/generic/Accessible.cpp
accessible/html/HTMLSelectAccessible.cpp
accessible/xul/XULSliderAccessible.cpp
accessible/xul/XULSliderAccessible.h
dom/base/DocumentFragment.h
dom/base/Element.h
dom/base/FragmentOrElement.cpp
dom/base/FragmentOrElement.h
dom/base/nsContentCreatorFunctions.h
dom/base/nsContentUtils.cpp
dom/base/nsDocument.cpp
dom/base/nsGenericDOMDataNode.cpp
dom/base/nsGenericDOMDataNode.h
dom/base/nsHTMLContentSerializer.cpp
dom/base/nsHTMLContentSerializer.h
dom/base/nsIContent.h
dom/base/nsINode.cpp
dom/base/nsIdentifierMapEntry.h
dom/base/nsObjectLoadingContent.cpp
dom/base/nsTreeSanitizer.cpp
dom/base/nsTreeSanitizer.h
dom/base/nsXHTMLContentSerializer.cpp
dom/base/nsXHTMLContentSerializer.h
dom/base/nsXMLContentSerializer.cpp
dom/base/nsXMLContentSerializer.h
dom/svg/SVGAElement.h
dom/svg/SVGStyleElement.h
dom/xbl/nsXBLBinding.cpp
dom/xbl/nsXBLBinding.h
dom/xbl/nsXBLContentSink.cpp
dom/xbl/nsXBLContentSink.h
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xbl/nsXBLPrototypeBinding.h
dom/xbl/nsXBLService.cpp
dom/xbl/nsXBLService.h
dom/xml/nsXMLContentSink.cpp
dom/xml/nsXMLContentSink.h
dom/xml/nsXMLPrettyPrinter.cpp
dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
dom/xslt/xslt/txMozillaTextOutput.cpp
dom/xslt/xslt/txMozillaTextOutput.h
dom/xslt/xslt/txMozillaXMLOutput.cpp
dom/xslt/xslt/txMozillaXMLOutput.h
dom/xul/XULDocument.cpp
dom/xul/XULDocument.h
dom/xul/nsIXULDocument.h
dom/xul/nsXULElement.cpp
dom/xul/nsXULElement.h
dom/xul/templates/nsIXULTemplateBuilder.idl
dom/xul/templates/nsXULContentBuilder.cpp
dom/xul/templates/nsXULContentUtils.cpp
dom/xul/templates/nsXULContentUtils.h
dom/xul/templates/nsXULSortService.cpp
dom/xul/templates/nsXULSortService.h
dom/xul/templates/nsXULTemplateBuilder.cpp
dom/xul/templates/nsXULTemplateBuilder.h
dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
dom/xul/templates/nsXULTemplateQueryProcessorRDF.h
dom/xul/templates/nsXULTreeBuilder.cpp
dom/xul/templates/nsXULTreeBuilder.h
editor/libeditor/EditorBase.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLStyleEditor.cpp
editor/libeditor/TextEditRules.cpp
gfx/layers/opengl/TexturePoolOGL.cpp
gfx/layers/opengl/TexturePoolOGL.h
js/src/jit-test/tests/baseline/bug843811-1.js
js/src/jit-test/tests/baseline/bug843811-2.js
js/src/jit-test/tests/baseline/bug843811-3.js
js/src/jit-test/tests/basic/bug640078.js
js/src/jit-test/tests/basic/bug787309.js
js/src/jit-test/tests/basic/bug787848.js
js/src/jit-test/tests/ion/bug799185-1.js
js/src/jit-test/tests/jaeger/bug553781-2.js
js/src/jit-test/tests/jaeger/bug553781.js
js/src/tests/ecma_5/extensions/iterator-in-catch.js
js/src/tests/js1_5/extensions/catchguard-001-n.js
js/src/tests/js1_5/extensions/catchguard-001.js
js/src/tests/js1_5/extensions/catchguard-002.js
js/src/tests/js1_5/extensions/catchguard-003.js
js/src/tests/js1_5/extensions/regress-346494-01.js
js/src/tests/js1_5/extensions/regress-346494.js
js/src/tests/js1_5/extensions/regress-350312-02.js
js/src/tests/js1_5/extensions/regress-350312-03.js
js/src/tests/js1_5/extensions/regress-351102-01.js
js/src/tests/js1_5/extensions/regress-351102-02.js
js/src/tests/js1_5/extensions/regress-351102-06.js
js/src/tests/js1_5/extensions/regress-374589.js
js/src/tests/js1_7/extensions/regress-351102-03.js
js/src/tests/js1_7/extensions/regress-351102-04.js
js/src/tests/js1_7/extensions/regress-351102-05.js
js/src/tests/js1_7/extensions/regress-351102-07.js
js/src/tests/js1_7/regress/regress-375695.js
js/src/tests/js1_8_5/extensions/regress-677589.js
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/forms/nsButtonFrameRenderer.cpp
layout/forms/nsComboboxControlFrame.h
layout/forms/nsDateTimeControlFrame.h
layout/forms/nsFileControlFrame.h
layout/forms/nsHTMLButtonControlFrame.cpp
layout/generic/ScrollbarActivity.cpp
layout/generic/ScrollbarActivity.h
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsVideoFrame.cpp
layout/generic/nsVideoFrame.h
layout/mathml/nsMathMLmactionFrame.cpp
layout/xul/PopupBoxObject.cpp
layout/xul/nsDeckFrame.cpp
layout/xul/nsIRootBox.h
layout/xul/nsMenuFrame.cpp
layout/xul/nsMenuPopupFrame.cpp
layout/xul/nsProgressMeterFrame.cpp
layout/xul/nsResizerFrame.cpp
layout/xul/nsRootBoxFrame.cpp
layout/xul/nsScrollbarButtonFrame.cpp
layout/xul/nsScrollbarFrame.cpp
layout/xul/nsSliderFrame.cpp
layout/xul/nsSplitterFrame.cpp
layout/xul/nsXULPopupManager.cpp
layout/xul/nsXULPopupManager.h
layout/xul/nsXULTooltipListener.cpp
layout/xul/tree/nsTreeBodyFrame.cpp
layout/xul/tree/nsTreeBodyFrame.h
layout/xul/tree/nsTreeColumns.cpp
layout/xul/tree/nsTreeContentView.cpp
layout/xul/tree/nsTreeContentView.h
layout/xul/tree/nsTreeUtils.cpp
layout/xul/tree/nsTreeUtils.h
parser/html/nsHtml5TreeOperation.cpp
testing/marionette/server.js
testing/web-platform/meta/css/css-overflow/input-scrollable-region-001.html.ini
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -1381,40 +1381,40 @@ aria::HasDefinedARIAHidden(nsIContent* a
 
 ////////////////////////////////////////////////////////////////////////////////
 // AttrIterator class
 
 bool
 AttrIterator::Next(nsAString& aAttrName, nsAString& aAttrValue)
 {
   while (mAttrIdx < mAttrCount) {
-    const nsAttrName* attr = mContent->GetAttrNameAt(mAttrIdx);
+    const nsAttrName* attr = mElement->GetAttrNameAt(mAttrIdx);
     mAttrIdx++;
     if (attr->NamespaceEquals(kNameSpaceID_None)) {
       nsAtom* attrAtom = attr->Atom();
       nsDependentAtomString attrStr(attrAtom);
       if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
         continue; // Not ARIA
 
       uint8_t attrFlags = aria::AttrCharacteristicsFor(attrAtom);
       if (attrFlags & ATTR_BYPASSOBJ)
         continue; // No need to handle exposing as obj attribute here
 
       if ((attrFlags & ATTR_VALTOKEN) &&
-           !nsAccUtils::HasDefinedARIAToken(mContent, attrAtom))
+           !nsAccUtils::HasDefinedARIAToken(mElement, attrAtom))
         continue; // only expose token based attributes if they are defined
 
       if ((attrFlags & ATTR_BYPASSOBJ_IF_FALSE) &&
-          mContent->AttrValueIs(kNameSpaceID_None, attrAtom,
+          mElement->AttrValueIs(kNameSpaceID_None, attrAtom,
                                 nsGkAtoms::_false, eCaseMatters)) {
         continue; // only expose token based attribute if value is not 'false'.
       }
 
       nsAutoString value;
-      if (mContent->GetAttr(kNameSpaceID_None, attrAtom, value)) {
+      if (mElement->GetAttr(kNameSpaceID_None, attrAtom, value)) {
         aAttrName.Assign(Substring(attrStr, 5));
         aAttrValue.Assign(value);
         return true;
       }
     }
   }
 
   return false;
--- a/accessible/base/ARIAMap.h
+++ b/accessible/base/ARIAMap.h
@@ -9,16 +9,17 @@
 #define mozilla_a11y_aria_ARIAMap_h_
 
 #include "ARIAStateMap.h"
 #include "mozilla/a11y/AccTypes.h"
 #include "mozilla/a11y/Role.h"
 
 #include "nsAtom.h"
 #include "nsIContent.h"
+#include "mozilla/dom/Element.h"
 
 class nsINode;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Value constants
 
 /**
  * Used to define if role requires to expose Value interface.
@@ -283,30 +284,31 @@ bool HasDefinedARIAHidden(nsIContent* aC
 
  /**
   * Represents a simple enumerator for iterating through ARIA attributes
   * exposed as object attributes on a given accessible.
   */
 class AttrIterator
 {
 public:
-  explicit AttrIterator(nsIContent* aContent) :
-    mContent(aContent), mAttrIdx(0)
+  explicit AttrIterator(nsIContent* aContent)
+    : mElement(aContent->IsElement() ? aContent->AsElement() : nullptr)
+    , mAttrIdx(0)
   {
-    mAttrCount = mContent->GetAttrCount();
+    mAttrCount = mElement ? mElement->GetAttrCount() : 0;
   }
 
   bool Next(nsAString& aAttrName, nsAString& aAttrValue);
 
 private:
   AttrIterator() = delete;
   AttrIterator(const AttrIterator&) = delete;
   AttrIterator& operator= (const AttrIterator&) = delete;
 
-  nsIContent* mContent;
+  dom::Element* mElement;
   uint32_t mAttrIdx;
   uint32_t mAttrCount;
 };
 
 } // namespace aria
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -109,30 +109,32 @@ using namespace mozilla::dom;
  * Return true if the element must be accessible.
  */
 static bool
 MustBeAccessible(nsIContent* aContent, DocAccessible* aDocument)
 {
   if (aContent->GetPrimaryFrame()->IsFocusable())
     return true;
 
-  uint32_t attrCount = aContent->GetAttrCount();
-  for (uint32_t attrIdx = 0; attrIdx < attrCount; attrIdx++) {
-    const nsAttrName* attr = aContent->GetAttrNameAt(attrIdx);
-    if (attr->NamespaceEquals(kNameSpaceID_None)) {
-      nsAtom* attrAtom = attr->Atom();
-      nsDependentAtomString attrStr(attrAtom);
-      if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
-        continue; // not ARIA
+  if (aContent->IsElement()) {
+    uint32_t attrCount = aContent->AsElement()->GetAttrCount();
+    for (uint32_t attrIdx = 0; attrIdx < attrCount; attrIdx++) {
+      const nsAttrName* attr = aContent->AsElement()->GetAttrNameAt(attrIdx);
+      if (attr->NamespaceEquals(kNameSpaceID_None)) {
+        nsAtom* attrAtom = attr->Atom();
+        nsDependentAtomString attrStr(attrAtom);
+        if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
+          continue; // not ARIA
 
-      // A global state or a property and in case of token defined.
-      uint8_t attrFlags = aria::AttrCharacteristicsFor(attrAtom);
-      if ((attrFlags & ATTR_GLOBAL) && (!(attrFlags & ATTR_VALTOKEN) ||
-           nsAccUtils::HasDefinedARIAToken(aContent, attrAtom))) {
-        return true;
+        // A global state or a property and in case of token defined.
+        uint8_t attrFlags = aria::AttrCharacteristicsFor(attrAtom);
+        if ((attrFlags & ATTR_GLOBAL) && (!(attrFlags & ATTR_VALTOKEN) ||
+             nsAccUtils::HasDefinedARIAToken(aContent, attrAtom))) {
+          return true;
+        }
       }
     }
   }
 
   // If the given ID is referred by relation attribute then create an accessible
   // for it.
   nsAutoString id;
   if (nsCoreUtils::GetID(aContent, id) && !id.IsEmpty())
--- a/accessible/generic/ARIAGridAccessible.cpp
+++ b/accessible/generic/ARIAGridAccessible.cpp
@@ -460,26 +460,28 @@ ARIAGridAccessible::GetCellInRowAt(Acces
 
 nsresult
 ARIAGridAccessible::SetARIASelected(Accessible* aAccessible,
                                     bool aIsSelected, bool aNotify)
 {
   if (IsARIARole(nsGkAtoms::table))
     return NS_OK;
 
-  nsIContent *content = aAccessible->GetContent();
+  nsIContent* content = aAccessible->GetContent();
   NS_ENSURE_STATE(content);
 
   nsresult rv = NS_OK;
-  if (aIsSelected)
-    rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
-                          NS_LITERAL_STRING("true"), aNotify);
-  else
-    rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
-                          NS_LITERAL_STRING("false"), aNotify);
+  if (content->IsElement()) {
+    if (aIsSelected)
+      rv = content->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
+                                         NS_LITERAL_STRING("true"), aNotify);
+    else
+      rv = content->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
+                                         NS_LITERAL_STRING("false"), aNotify);
+  }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // No "smart" select/unselect for internal call.
   if (!aNotify)
     return NS_OK;
 
   // If row or cell accessible was selected then we're able to not bother about
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -699,22 +699,24 @@ void
 Accessible::SetSelected(bool aSelect)
 {
   if (!HasOwnContent())
     return;
 
   Accessible* select = nsAccUtils::GetSelectableContainer(this, State());
   if (select) {
     if (select->State() & states::MULTISELECTABLE) {
-      if (ARIARoleMap()) {
+      if (mContent->IsElement() && ARIARoleMap()) {
         if (aSelect) {
-          mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
-                            NS_LITERAL_STRING("true"), true);
+          mContent->AsElement()->SetAttr(kNameSpaceID_None,
+                                         nsGkAtoms::aria_selected,
+                                         NS_LITERAL_STRING("true"), true);
         } else {
-          mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected, true);
+          mContent->AsElement()->UnsetAttr(kNameSpaceID_None,
+                                           nsGkAtoms::aria_selected, true);
         }
       }
       return;
     }
 
     if (aSelect)
       TakeFocus();
   }
@@ -1411,18 +1413,22 @@ Accessible::SetCurValue(double aValue)
 
   checkValue = MaxValue();
   if (!IsNaN(checkValue) && aValue > checkValue)
     return false;
 
   nsAutoString strValue;
   strValue.AppendFloat(aValue);
 
+  if (!mContent->IsElement())
+    return true;
+
   return NS_SUCCEEDED(
-    mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow, strValue, true));
+    mContent->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow,
+                                   strValue, true));
 }
 
 role
 Accessible::ARIATransformRole(role aRole)
 {
   // Beginning with ARIA 1.1, user agents are expected to use the native host
   // language role of the element when the region role is used without a name.
   // https://rawgit.com/w3c/aria/master/core-aam/core-aam.html#role-map-region
@@ -2565,18 +2571,20 @@ Accessible::CurrentItem()
 
 void
 Accessible::SetCurrentItem(Accessible* aItem)
 {
   nsAtom* id = aItem->GetContent()->GetID();
   if (id) {
     nsAutoString idStr;
     id->ToString(idStr);
-    mContent->SetAttr(kNameSpaceID_None,
-                      nsGkAtoms::aria_activedescendant, idStr, true);
+    mContent->AsElement()->SetAttr(kNameSpaceID_None,
+                                   nsGkAtoms::aria_activedescendant,
+                                   idStr,
+                                   true);
   }
 }
 
 Accessible*
 Accessible::ContainerWidget() const
 {
   if (HasARIARole() && mContent->HasID()) {
     for (Accessible* parent = Parent(); parent; parent = parent->Parent()) {
--- a/accessible/html/HTMLSelectAccessible.cpp
+++ b/accessible/html/HTMLSelectAccessible.cpp
@@ -105,19 +105,23 @@ HTMLSelectListAccessible::CurrentItem()
     }
   }
   return nullptr;
 }
 
 void
 HTMLSelectListAccessible::SetCurrentItem(Accessible* aItem)
 {
-  aItem->GetContent()->SetAttr(kNameSpaceID_None,
-                               nsGkAtoms::selected, NS_LITERAL_STRING("true"),
-                               true);
+  if (!aItem->GetContent()->IsElement())
+    return;
+
+  aItem->GetContent()->AsElement()->SetAttr(kNameSpaceID_None,
+                                            nsGkAtoms::selected,
+                                            NS_LITERAL_STRING("true"),
+                                            true);
 }
 
 bool
 HTMLSelectListAccessible::IsAcceptableChild(nsIContent* aEl) const
 {
   return aEl->IsAnyOfHTMLElements(nsGkAtoms::option, nsGkAtoms::optgroup);
 }
 
--- a/accessible/xul/XULSliderAccessible.cpp
+++ b/accessible/xul/XULSliderAccessible.cpp
@@ -8,17 +8,18 @@
 #include "nsAccessibilityService.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsIFrame.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/FloatingPoint.h"
 
-using namespace mozilla::a11y;
+namespace mozilla {
+namespace a11y {
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULSliderAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULSliderAccessible::
   XULSliderAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
@@ -35,17 +36,17 @@ XULSliderAccessible::NativeRole()
 }
 
 uint64_t
 XULSliderAccessible::NativeInteractiveState() const
  {
   if (NativelyUnavailable())
     return states::UNAVAILABLE;
 
-  nsIContent* sliderElm = GetSliderElement();
+  dom::Element* sliderElm = GetSliderElement();
   if (sliderElm) {
     nsIFrame* frame = sliderElm->GetPrimaryFrame();
     if (frame && frame->IsFocusable())
       return states::FOCUSABLE;
   }
 
   return 0;
 }
@@ -78,17 +79,17 @@ XULSliderAccessible::ActionNameAt(uint8_
 }
 
 bool
 XULSliderAccessible::DoAction(uint8_t aIndex)
 {
   if (aIndex != 0)
     return false;
 
-  nsIContent* sliderElm = GetSliderElement();
+  dom::Element* sliderElm = GetSliderElement();
   if (sliderElm)
     DoCommand(sliderElm);
 
   return true;
 }
 
 double
 XULSliderAccessible::MaxValue() const
@@ -124,27 +125,27 @@ XULSliderAccessible::SetCurValue(double 
   if (AccessibleWrap::SetCurValue(aValue))
     return true;
 
   return SetSliderAttr(nsGkAtoms::curpos, aValue);
 }
 
 // Utils
 
-nsIContent*
+dom::Element*
 XULSliderAccessible::GetSliderElement() const
 {
-  if (!mSliderNode) {
+  if (!mSliderElement) {
     // XXX: we depend on anonymous content.
-    mSliderNode = mContent->OwnerDoc()->
+    mSliderElement = mContent->OwnerDoc()->
       GetAnonymousElementByAttribute(mContent, nsGkAtoms::anonid,
                                      NS_LITERAL_STRING("slider"));
   }
 
-  return mSliderNode;
+  return mSliderElement;
 }
 
 nsresult
 XULSliderAccessible::GetSliderAttr(nsAtom* aName, nsAString& aValue) const
 {
   aValue.Truncate();
 
   if (IsDefunct())
@@ -158,18 +159,17 @@ XULSliderAccessible::GetSliderAttr(nsAto
 }
 
 nsresult
 XULSliderAccessible::SetSliderAttr(nsAtom* aName, const nsAString& aValue)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsIContent* sliderElm = GetSliderElement();
-  if (sliderElm)
+  if (dom::Element* sliderElm = GetSliderElement())
     sliderElm->SetAttr(kNameSpaceID_None, aName, aValue, true);
 
   return NS_OK;
 }
 
 double
 XULSliderAccessible::GetSliderAttr(nsAtom* aName) const
 {
@@ -207,8 +207,10 @@ XULThumbAccessible::
 // XULThumbAccessible: Accessible
 
 role
 XULThumbAccessible::NativeRole()
 {
   return roles::INDICATOR;
 }
 
+}
+}
--- a/accessible/xul/XULSliderAccessible.h
+++ b/accessible/xul/XULSliderAccessible.h
@@ -38,26 +38,26 @@ public:
   virtual uint8_t ActionCount() override;
   virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
   virtual bool DoAction(uint8_t aIndex) override;
 
 protected:
   /**
    * Return anonymous slider element.
    */
-  nsIContent* GetSliderElement() const;
+  dom::Element* GetSliderElement() const;
 
   nsresult GetSliderAttr(nsAtom *aName, nsAString& aValue) const;
   nsresult SetSliderAttr(nsAtom *aName, const nsAString& aValue);
 
   double GetSliderAttr(nsAtom *aName) const;
   bool SetSliderAttr(nsAtom *aName, double aValue);
 
 private:
-  mutable nsCOMPtr<nsIContent> mSliderNode;
+  mutable RefPtr<dom::Element> mSliderElement;
 };
 
 
 /**
  * Used for slider's thumb element.
  */
 class XULThumbAccessible : public AccessibleWrap
 {
--- a/browser/base/content/browser-pageActions.js
+++ b/browser/base/content/browser-pageActions.js
@@ -946,17 +946,17 @@ BrowserPageActions.emailLink = {
 // send to device
 BrowserPageActions.sendToDevice = {
   onPlacedInPanel(buttonNode) {
     let action = PageActions.actionForID("sendToDevice");
     BrowserPageActions.takeActionTitleFromPanel(action);
   },
 
   onSubviewPlaced(panelViewNode) {
-    let bodyNode = panelViewNode.firstChild;
+    let bodyNode = panelViewNode.querySelector(".panel-subview-body");
     for (let node of bodyNode.childNodes) {
       BrowserPageActions.takeNodeAttributeFromPanel(node, "title");
       BrowserPageActions.takeNodeAttributeFromPanel(node, "shortcut");
     }
   },
 
   onLocationChange() {
     let action = PageActions.actionForID("sendToDevice");
@@ -965,17 +965,17 @@ BrowserPageActions.sendToDevice = {
     action.setDisabled(!gSync.isSendableURI(url), window);
   },
 
   onShowingSubview(panelViewNode) {
     let browser = gBrowser.selectedBrowser;
     let url = browser.currentURI.spec;
     let title = browser.contentTitle;
 
-    let bodyNode = panelViewNode.firstChild;
+    let bodyNode = panelViewNode.querySelector(".panel-subview-body");
     let panelNode = panelViewNode.closest("panel");
 
     // This is on top because it also clears the device list between state
     // changes.
     gSync.populateSendTabToDevicesMenu(bodyNode, url, title, (clientId, name, clientType, lastModified) => {
       if (!name) {
         return document.createElement("toolbarseparator");
       }
--- a/browser/base/content/browser-sidebar.js
+++ b/browser/base/content/browser-sidebar.js
@@ -441,16 +441,27 @@ var SidebarUI = {
       let selBrowser = gBrowser.selectedBrowser;
       selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
         {commandID, isOpen: true}
       );
     });
   },
 
   /**
+  * Sets the webpage favicon in sidebar
+  *
+  */
+  setWebPageIcon(url) {
+    let iconURL = "url(page-icon:" + url + ")";
+    if (this._box.getAttribute("sidebarcommand") == "viewWebPanelsSidebar") {
+      this._icon.style.setProperty("--sidebar-webpage-icon", iconURL);
+    }
+  },
+
+  /**
    * Hide the sidebar.
    *
    * @param {DOMNode} [triggerNode] Node, usually a button, that triggered the
    *                                hiding of the sidebar.
    */
   hide(triggerNode) {
     if (!this.isOpen) {
       return;
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -68,31 +68,29 @@ toolbar[customizable="true"] {
 }
 
 panelmultiview {
   -moz-box-align: start;
   -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelmultiview");
 }
 
 panelview {
-  -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelview");
   -moz-box-orient: vertical;
 }
 
-panel[hidden] panelmultiview,
-panel[hidden] panelview {
+panel[hidden] panelmultiview {
   -moz-binding: none;
 }
 
 panelview:not([current]):not([in-transition]) {
   visibility: collapse;
 }
 
-panelview[mainview] > .panel-header,
-panelview:not([title]) > .panel-header {
+/* Hide the header when a subview is reused as a main view. */
+panelview[mainview] > .panel-header {
   display: none;
 }
 
 tabbrowser {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
 }
 
 #tabbrowser-tabs {
@@ -1402,16 +1400,26 @@ toolbarpaletteitem[place="palette"][hidd
 }
 #pageActionContextMenu[state=builtInPinned] > .pageActionContextMenuItem.builtInPinned,
 #pageActionContextMenu[state=builtInUnpinned] > .pageActionContextMenuItem.builtInUnpinned,
 #pageActionContextMenu[state=extensionPinned] > .pageActionContextMenuItem.extensionPinned,
 #pageActionContextMenu[state=extensionUnpinned] > .pageActionContextMenuItem.extensionUnpinned {
   visibility: visible;
 }
 
+
+/* Favicon in Open Bookmark in Sidebar */
+#sidebar-box[sidebarcommand="viewWebPanelsSidebar"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
+  list-style-image: var(--sidebar-webpage-icon, url(chrome://mozapps/skin/places/defaultFavicon.svg) );
+  -moz-context-properties: fill;
+  fill: currentColor;
+  width: 16px;
+  height: 16px;
+}
+
 /* WebExtension Sidebars */
 #sidebar-box[sidebarcommand$="-sidebar-action"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
   list-style-image: var(--webextension-menuitem-image, inherit);
   -moz-context-properties: fill;
   fill: currentColor;
   width: 16px;
   height: 16px;
 }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5784,16 +5784,17 @@ function openWebPanel(title, uri) {
     gWebPanelURI = uri;
   }
 }
 
 function asyncOpenWebPanel(event) {
   if (gWebPanelURI && SidebarUI.browser.contentDocument &&
       SidebarUI.browser.contentDocument.getElementById("web-panels-browser")) {
     SidebarUI.browser.contentWindow.loadWebPanel(gWebPanelURI);
+    SidebarUI.setWebPageIcon(gWebPanelURI);
   }
   gWebPanelURI = "";
   SidebarUI.browser.removeEventListener("load", asyncOpenWebPanel, true);
 }
 
 /*
  * - [ Dependencies ] ---------------------------------------------------------
  *  utilityOverlay.js:
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -273,33 +273,33 @@
            flip="slide"
            orient="vertical"
            position="bottomcenter topleft">
       <toolbarbutton id="sidebar-switcher-bookmarks"
                      class="subviewbutton subviewbutton-iconic"
                      key="viewBookmarksSidebarKb"
                      observes="viewBookmarksSidebar"
                      oncommand="SidebarUI.show('viewBookmarksSidebar');">
-         <observes element="viewBookmarksSidebar" attribute="checked"/>
-       </toolbarbutton>
+        <observes element="viewBookmarksSidebar" attribute="checked"/>
+      </toolbarbutton>
       <toolbarbutton id="sidebar-switcher-history"
                      label="&historyButton.label;"
                      class="subviewbutton subviewbutton-iconic"
                      key="key_gotoHistory"
                      observes="viewHistorySidebar"
                      oncommand="SidebarUI.show('viewHistorySidebar');">
-         <observes element="viewHistorySidebar" attribute="checked"/>
-       </toolbarbutton>
+        <observes element="viewHistorySidebar" attribute="checked"/>
+      </toolbarbutton>
       <toolbarbutton id="sidebar-switcher-tabs"
                      label="&syncedTabs.sidebar.label;"
                      class="subviewbutton subviewbutton-iconic"
                      observes="viewTabsSidebar"
                      oncommand="SidebarUI.show('viewTabsSidebar');">
-         <observes element="viewTabsSidebar" attribute="checked"/>
-       </toolbarbutton>
+        <observes element="viewTabsSidebar" attribute="checked"/>
+      </toolbarbutton>
       <toolbarseparator/>
       <vbox id="sidebar-extensions"></vbox>
       <toolbarseparator/>
       <toolbarbutton id="sidebar-reverse-position"
                      class="subviewbutton"
                      oncommand="SidebarUI.reversePosition()"/>
       <toolbarseparator/>
       <toolbarbutton label="&sidebarMenuClose.label;"
--- a/browser/base/content/test/popupNotifications/browser_displayURI.js
+++ b/browser/base/content/test/popupNotifications/browser_displayURI.js
@@ -1,24 +1,75 @@
 /*
- * Make sure that the origin is shown for ContentPermissionPrompt
- * consumers e.g. geolocation.
-*/
+ * Make sure that the correct origin is shown for permission prompts.
+ */
 
-add_task(async function test_displayURI() {
-  await BrowserTestUtils.withNewTab({
-    gBrowser,
-    url: "https://test1.example.com/",
-  }, async function(browser) {
+async function check(contentTask) {
+  await BrowserTestUtils.withNewTab("https://test1.example.com/", async function(browser) {
     let popupShownPromise = waitForNotificationPanel();
-    await ContentTask.spawn(browser, null, async function() {
-      content.navigator.geolocation.getCurrentPosition(function(pos) {
-        // Do nothing
-      });
-    });
+    await ContentTask.spawn(browser, null, contentTask);
     let panel = await popupShownPromise;
     let notification = panel.children[0];
     let body = document.getAnonymousElementByAttribute(notification,
                                                        "class",
                                                        "popup-notification-body");
     ok(body.innerHTML.includes("example.com"), "Check that at least the eTLD+1 is present in the markup");
   });
+
+  let channel = NetUtil.newChannel({
+    uri: getRootDirectory(gTestPath),
+    loadUsingSystemPrincipal: true,
+  });
+  channel = channel.QueryInterface(Ci.nsIFileChannel);
+
+  return BrowserTestUtils.withNewTab(channel.file.path, async function(browser) {
+    let popupShownPromise = waitForNotificationPanel();
+    await ContentTask.spawn(browser, null, contentTask);
+    let panel = await popupShownPromise;
+    let notification = panel.children[0];
+    let body = document.getAnonymousElementByAttribute(notification,
+                                                       "class",
+                                                       "popup-notification-body");
+    if (notification.id == "geolocation-notification") {
+      ok(body.innerHTML.includes("local file"), `file:// URIs should be displayed as local file.`);
+    } else {
+      ok(body.innerHTML.includes("Unknown origin"), "file:// URIs should be displayed as unknown origin.");
+    }
+  });
+}
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({set: [
+    ["media.navigator.permission.fake", true],
+    ["media.navigator.permission.force", true],
+  ]});
 });
+
+add_task(async function test_displayURI_geo() {
+  await check(async function() {
+    content.navigator.geolocation.getCurrentPosition(() => {});
+  });
+});
+
+add_task(async function test_displayURI_camera() {
+  await check(async function() {
+    content.navigator.mediaDevices.getUserMedia({video: true, fake: true});
+  });
+});
+
+add_task(async function test_displayURI_geo_blob() {
+  await check(async function() {
+    let text = "<script>navigator.geolocation.getCurrentPosition(() => {})</script>";
+    let blob = new Blob([text], {type: "text/html"});
+    let url = content.URL.createObjectURL(blob);
+    content.location.href = url;
+  });
+});
+
+add_task(async function test_displayURI_camera_blob() {
+  await check(async function() {
+    let text = "<script>navigator.mediaDevices.getUserMedia({video: true, fake: true})</script>";
+    let blob = new Blob([text], {type: "text/html"});
+    let url = content.URL.createObjectURL(blob);
+    content.location.href = url;
+  });
+});
+
--- a/browser/base/content/test/webrtc/get_user_media.html
+++ b/browser/base/content/test/webrtc/get_user_media.html
@@ -27,17 +27,18 @@ var gStreams = [];
 
 function requestDevice(aAudio, aVideo, aShare, aBadDevice = false) {
   var opts = {video: aVideo, audio: aAudio};
   if (aShare) {
     opts.video = {
       mozMediaSource: aShare,
       mediaSource: aShare
     };
-  } else if (useFakeStreams) {
+  }
+  if (useFakeStreams) {
     opts.fake = true;
   }
 
   if (aVideo && aBadDevice) {
     opts.video = {
       deviceId: "bad device"
     };
     opts.fake = true;
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -363,19 +363,59 @@ this.PanelMultiView = class {
   }
 
   _placeSubView(viewNode) {
     this._viewStack.appendChild(viewNode);
     if (!this.panelViews.includes(viewNode))
       this.panelViews.push(viewNode);
   }
 
-  goBack(target) {
+  _setHeader(viewNode, titleText) {
+    // If the header already exists, update or remove it as requested.
+    let header = viewNode.firstChild;
+    if (header && header.classList.contains("panel-header")) {
+      if (titleText) {
+        header.querySelector("label").setAttribute("value", titleText);
+      } else {
+        header.remove();
+      }
+      return;
+    }
+
+    // The header doesn't exist, only create it if needed.
+    if (!titleText) {
+      return;
+    }
+
+    header = this.document.createElement("box");
+    header.classList.add("panel-header");
+
+    let backButton = this.document.createElement("toolbarbutton");
+    backButton.className =
+      "subviewbutton subviewbutton-iconic subviewbutton-back";
+    backButton.setAttribute("closemenu", "none");
+    backButton.setAttribute("tabindex", "0");
+    backButton.setAttribute("tooltip",
+      this.node.getAttribute("data-subviewbutton-tooltip"));
+    backButton.addEventListener("command", () => {
+      // The panelmultiview element may change if the view is reused.
+      viewNode.panelMultiView.goBack();
+      backButton.blur();
+    });
+
+    let label = this.document.createElement("label");
+    label.setAttribute("value", titleText);
+
+    header.append(backButton, label);
+    viewNode.prepend(header);
+  }
+
+  goBack() {
     let [current, previous] = this.panelViews.back();
-    return this.showSubView(current, target, previous);
+    return this.showSubView(current, null, previous);
   }
 
   /**
    * Checks whether it is possible to navigate backwards currently. Returns
    * false if this is the panelmultiview's mainview, true otherwise.
    *
    * @param  {panelview} view View to check, defaults to the currently active view.
    * @return {Boolean}
@@ -449,16 +489,20 @@ this.PanelMultiView = class {
           this._placeSubView(viewNode);
         } else {
           throw new Error(`Subview ${aViewId} doesn't exist!`);
         }
       } else if (viewNode.parentNode == this._panelViewCache) {
         this._placeSubView(viewNode);
       }
 
+      viewNode.panelMultiView = this.node;
+      this._setHeader(viewNode, viewNode.getAttribute("title") ||
+                                (aAnchor && aAnchor.getAttribute("label")));
+
       let reverse = !!aPreviousView;
       let previousViewNode = aPreviousView || this._currentSubView;
       // If the panelview to show is the same as the previous one, the 'ViewShowing'
       // event has already been dispatched. Don't do it twice.
       let showingSameView = viewNode == previousViewNode;
       let playTransition = (!!previousViewNode && !showingSameView && this._panel.state == "open");
       let isMainView = viewNode.id == this._mainViewId;
 
@@ -483,20 +527,17 @@ this.PanelMultiView = class {
       // Because the 'mainview' attribute may be out-of-sync, due to view node
       // reparenting in combination with ephemeral PanelMultiView instances,
       // this is the best place to correct it (just before showing).
       if (isMainView)
         viewNode.setAttribute("mainview", true);
       else
         viewNode.removeAttribute("mainview");
 
-      // Make sure that new panels always have a title set.
       if (aAnchor) {
-        if (!viewNode.hasAttribute("title"))
-          viewNode.setAttribute("title", aAnchor.getAttribute("label"));
         viewNode.classList.add("PanelUI-subView");
       }
       if (!isMainView && this._mainViewWidth)
         viewNode.style.maxWidth = viewNode.style.minWidth = this._mainViewWidth + "px";
 
       if (!showingSameView || !viewNode.hasAttribute("current")) {
         // Emit the ViewShowing event so that the widget definition has a chance
         // to lazily populate the subview with things or perhaps even cancel this
@@ -594,18 +635,18 @@ this.PanelMultiView = class {
       // reopening a subview, because its contents may have changed.
       viewRect = viewNode.__lastKnownBoundingRect;
       viewNode.setAttribute("in-transition", true);
     } else if (viewNode.customRectGetter) {
       // Can't use Object.assign directly with a DOM Rect object because its properties
       // aren't enumerable.
       let {height, width} = previousRect;
       viewRect = Object.assign({height, width}, viewNode.customRectGetter());
-      let {header} = viewNode;
-      if (header) {
+      let header = viewNode.firstChild;
+      if (header && header.classList.contains("panel-header")) {
         viewRect.height += this._dwu.getBoundsWithoutFlushing(header).height;
       }
       viewNode.setAttribute("in-transition", true);
     } else {
       let oldSibling = viewNode.nextSibling || null;
       this._offscreenViewStack.style.minHeight =
         this._viewContainer.style.height;
       this._offscreenViewStack.appendChild(viewNode);
@@ -1018,17 +1059,17 @@ this.PanelMultiView = class {
       }
       case "ArrowLeft":
       case "ArrowRight": {
         stop();
         let dir = this._dir;
         if ((dir == "ltr" && keyCode == "ArrowLeft") ||
             (dir == "rtl" && keyCode == "ArrowRight")) {
           if (this._canGoBack(view))
-            this.goBack(view.backButton);
+            this.goBack();
           break;
         }
         // If the current button is _not_ one that points to a subview, pressing
         // the arrow key shouldn't do anything.
         if (!navMap.selected || !navMap.selected.get() ||
             !navMap.selected.get().classList.contains("subviewbutton-nav")) {
           break;
         }
@@ -1084,18 +1125,16 @@ this.PanelMultiView = class {
    * Retrieve the button elements from a view node that can be used for navigation
    * using the keyboard; enabled buttons and the back button, if visible.
    *
    * @param  {nsIDOMNode} view
    * @return {Array}
    */
   _getNavigableElements(view) {
     let buttons = Array.from(view.querySelectorAll(".subviewbutton:not([disabled])"));
-    if (this._canGoBack(view))
-      buttons.unshift(view.backButton);
     let dwu = this._dwu;
     return buttons.filter(button => {
       let bounds = dwu.getBoundsWithoutFlushing(button);
       return bounds.width > 0 && bounds.height > 0;
     });
   }
 
   /**
--- a/browser/components/customizableui/content/panelUI.xml
+++ b/browser/components/customizableui/content/panelUI.xml
@@ -12,17 +12,17 @@
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="panelmultiview">
     <resources>
       <stylesheet src="chrome://browser/content/customizableui/panelUI.css"/>
     </resources>
-    <content>
+    <content data-subviewbutton-tooltip="&backCmd.label;">
       <xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,transitioning">
         <xul:box anonid="viewStack" xbl:inherits="transitioning" class="panel-viewstack">
           <children includes="panelview"/>
         </xul:box>
       </xul:box>
       <xul:box class="panel-viewcontainer offscreen">
         <xul:box anonid="offscreenViewStack" class="panel-viewstack"/>
       </xul:box>
@@ -33,41 +33,9 @@
         this.instance = new PanelMultiView(this);
       ]]></constructor>
 
       <destructor><![CDATA[
         this.instance.destructor();
       ]]></destructor>
     </implementation>
   </binding>
-
-  <binding id="panelview">
-    <content>
-      <xul:box class="panel-header" anonid="header">
-        <xul:toolbarbutton anonid="back"
-                           class="subviewbutton subviewbutton-iconic subviewbutton-back"
-                           closemenu="none"
-                           tabindex="0"
-                           tooltip="&backCmd.label;"
-                           oncommand="document.getBindingParent(this).panelMultiView.goBack(); this.blur()"/>
-        <xul:label xbl:inherits="value=title"/>
-      </xul:box>
-      <children/>
-    </content>
-    <implementation>
-      <property name="header"
-                readonly="true"
-                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'header');"/>
-      <property name="backButton"
-                readonly="true"
-                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'back');"/>
-      <property name="panelMultiView" readonly="true">
-        <getter><![CDATA[
-          if (!this.parentNode.localName.endsWith("panelmultiview")) {
-            return document.getBindingParent(this.parentNode);
-          }
-
-          return this.parentNode;
-        ]]></getter>
-      </property>
-    </implementation>
-  </binding>
 </bindings>
--- a/browser/components/customizableui/test/browser_987640_charEncoding.js
+++ b/browser/components/customizableui/test/browser_987640_charEncoding.js
@@ -24,17 +24,17 @@ add_task(async function() {
   charEncodingButton.click();
   await subviewShownPromise;
 
   let checkedButtons = characterEncodingView.querySelectorAll("toolbarbutton[checked='true']");
   let initialEncoding = checkedButtons[0];
   is(initialEncoding.getAttribute("label"), "Western", "The western encoding is initially selected");
 
   // change the encoding
-  let encodings = characterEncodingView.querySelectorAll("toolbarbutton");
+  let encodings = characterEncodingView.querySelectorAll("toolbarbutton:not(.subviewbutton-back)");
   let newEncoding = encodings[0].hasAttribute("checked") ? encodings[1] : encodings[0];
   let browserStopPromise = BrowserTestUtils.browserStopped(gBrowser, TEST_PAGE);
   newEncoding.click();
   await browserStopPromise;
   is(gBrowser.selectedBrowser.characterSet, "UTF-8", "The encoding should be changed to UTF-8");
   ok(!gBrowser.selectedBrowser.mayEnableCharacterEncodingMenu, "The encoding menu should be disabled");
 
   // check that the new encodng is applied
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -143,17 +143,16 @@ const listeners = {
   mm: {
     "AboutHome:MaybeShowMigrateMessage": ["AboutHome"],
     "AboutHome:RequestUpdate": ["AboutHome"],
     "Content:Click": ["ContentClick"],
     "ContentSearch": ["ContentSearch"],
     "FormValidation:ShowPopup": ["FormValidationHandler"],
     "FormValidation:HidePopup": ["FormValidationHandler"],
     "Prompt:Open": ["RemotePrompt"],
-    "Reader:ArticleGet": ["ReaderParent"],
     "Reader:FaviconRequest": ["ReaderParent"],
     "Reader:UpdateReaderButton": ["ReaderParent"],
     // PLEASE KEEP THIS LIST IN SYNC WITH THE MOBILE LISTENERS IN BrowserCLH.js
     "RemoteLogins:findLogins": ["LoginManagerParent"],
     "RemoteLogins:findRecipes": ["LoginManagerParent"],
     "RemoteLogins:onFormSubmit": ["LoginManagerParent"],
     "RemoteLogins:autoCompleteLogins": ["LoginManagerParent"],
     "RemoteLogins:removeLogin": ["LoginManagerParent"],
--- a/browser/modules/ContentWebRTC.jsm
+++ b/browser/modules/ContentWebRTC.jsm
@@ -211,16 +211,17 @@ function prompt(aContentWindow, aWindowI
   if (!aContentWindow.pendingGetUserMediaRequests) {
     setupPendingListsInitially(aContentWindow);
   }
   aContentWindow.pendingGetUserMediaRequests.set(aCallID, devices);
 
   let request = {
     callID: aCallID,
     windowID: aWindowID,
+    origin: aContentWindow.origin,
     documentURI: aContentWindow.document.documentURI,
     secure: aSecure,
     requestTypes,
     sharingScreen,
     sharingAudio,
     audioDevices,
     videoDevices
   };
--- a/browser/modules/ReaderParent.jsm
+++ b/browser/modules/ReaderParent.jsm
@@ -17,32 +17,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "UITour", "resource:///modules/UITour.jsm");
 
 const gStringBundle = Services.strings.createBundle("chrome://global/locale/aboutReader.properties");
 
 var ReaderParent = {
   // Listeners are added in nsBrowserGlue.js
   receiveMessage(message) {
     switch (message.name) {
-      case "Reader:ArticleGet":
-        this._getArticle(message.data.url, message.target).then((article) => {
-          // Make sure the target browser is still alive before trying to send data back.
-          if (message.target.messageManager) {
-            message.target.messageManager.sendAsyncMessage("Reader:ArticleData", { article });
-          }
-        }, e => {
-          if (e && e.newURL) {
-            // Make sure the target browser is still alive before trying to send data back.
-            if (message.target.messageManager) {
-              message.target.messageManager.sendAsyncMessage("Reader:ArticleData", { newURL: e.newURL });
-            }
-          }
-        });
-        break;
-
       case "Reader:FaviconRequest": {
         if (message.target.messageManager) {
           let faviconUrl = PlacesUtils.promiseFaviconLinkUrl(message.data.url);
           faviconUrl.then(function onResolution(favicon) {
             message.target.messageManager.sendAsyncMessage("Reader:FaviconReturn", {
               url: message.data.url,
               faviconUrl: favicon.path.replace(/^favicon:/, "")
             });
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -363,17 +363,23 @@ function prompt(aBrowser, aRequest) {
     return;
   }
 
   // Tell the browser to refresh the identity block display in case there
   // are expired permission states.
   aBrowser.dispatchEvent(new aBrowser.ownerGlobal
                                      .CustomEvent("PermissionStateChange"));
 
-  let uri = Services.io.newURI(aRequest.documentURI);
+  let uri;
+  try {
+    // This fails for principals that serialize to "null", e.g. file URIs.
+    uri = Services.io.newURI(aRequest.origin);
+  } catch (e) {
+    uri = Services.io.newURI(aRequest.documentURI);
+  }
   let host = getHost(uri);
   let chromeDoc = aBrowser.ownerDocument;
   let stringBundle = chromeDoc.defaultView.gNavigatorBundle;
 
   // Mind the order, because for simplicity we're iterating over the list using
   // "includes()". This allows the rotation of string identifiers. We list the
   // full identifiers here so they can be cross-referenced more easily.
   let joinedRequestTypes = requestTypes.join("And");
--- a/browser/themes/osx/customizableui/panelUI.css
+++ b/browser/themes/osx/customizableui/panelUI.css
@@ -30,24 +30,16 @@ panelmultiview .toolbaritem-combined-but
   padding-inline-start: 34px;
   margin-inline-start: -34px;
 }
 
 #appMenu-fxa-container[fxastatus="signedin"] > #appMenu-fxa-status > #appMenu-fxa-avatar {
   margin-inline-start: 18px;
 }
 
-.subviewbutton[checked="true"] {
-  background-position: top 7px left 4px;
-}
-
-.subviewbutton[checked="true"]:-moz-locale-dir(rtl) {
-  background-position: top 7px right 4px;
-}
-
 .subviewbutton:not(:-moz-any([image],[targetURI],.cui-withicon, .bookmark-item)) > .menu-iconic-left {
   display: none;
 }
 
 /* Override OSX-specific toolkit styles for the bookmarks panel */
 menu.subviewbutton > .menu-right {
   margin-inline-end: 0;
   -moz-appearance: none;
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -1482,28 +1482,28 @@ menuitem[checked="true"].subviewbutton >
   font-size: 13px;
   font-weight: 500;
   margin: 0;
   /* Add the size of the back button to center properly. */
   margin-inline-end: 32px;
   text-align: center;
 }
 
-.PanelUI-subView .panel-header > .subviewbutton-back {
+.panel-header > .subviewbutton-back {
   -moz-context-properties: fill;
   fill: var(--arrowpanel-color);
   list-style-image: url(chrome://browser/skin/arrow-left.svg);
   padding: 8px;
 }
 
-.panel-header > .subviewbutton-back:-moz-locale-dir(rtl) {
+.subviewbutton-back:-moz-locale-dir(rtl) {
   transform: scaleX(-1);
 }
 
-.panel-header > .subviewbutton-back > .toolbarbutton-text {
+.subviewbutton-back > .toolbarbutton-text {
   /* !important to override .cui-widget-panel toolbarbutton:not([wrap]) > .toolbarbutton-text
    * selector further down. */
   display: none !important;
 }
 
 #panelMenu_pocket {
   display: none;
 }
--- a/browser/themes/shared/sidebar.inc.css
+++ b/browser/themes/shared/sidebar.inc.css
@@ -95,32 +95,53 @@
 #sidebarMenu-popup .subviewbutton {
   min-width: 190px;
 }
 
 #sidebar-extensions:empty + toolbarseparator {
   display: none;
 }
 
-%ifndef XP_MACOSX
+#sidebarMenu-popup > .subviewbutton[checked="true"] {
+  list-style-image: none;
+  background: url(chrome://browser/skin/check.svg) no-repeat transparent;
+  background-size: 11px 11px;
+}
+
+%ifdef XP_MACOSX
+
+#sidebarMenu-popup > .subviewbutton[checked="true"] {
+  background-position: top 7px left 4px;
+}
+
+#sidebarMenu-popup > .subviewbutton[checked="true"]:-moz-locale-dir(rtl) {
+  background-position: top 7px right 4px;
+}
+
+%else
+
+#sidebarMenu-popup > .subviewbutton[checked="true"] {
+  background-position: center left 7px;
+}
+
+#sidebarMenu-popup > .subviewbutton[checked="true"]:-moz-locale-dir(rtl) {
+  background-position: center right 7px;
+}
+
 /* Allow room for the checkbox drawn as a background image at the start of the toolbarbutton */
-#sidebarMenu-popup .subviewbutton-iconic > .toolbarbutton-icon {
+#sidebarMenu-popup > .subviewbutton-iconic > .toolbarbutton-icon {
   margin-inline-start: 16px;
 }
 /* Align items without icons to the start of the icons: */
-#sidebarMenu-popup .subviewbutton:not(.subviewbutton-iconic) > .toolbarbutton-text {
+#sidebarMenu-popup > .subviewbutton:not(.subviewbutton-iconic) > .toolbarbutton-text {
   padding-inline-start: 16px;
 }
+
 %endif
 
-
-#sidebar-box[sidebarcommand="viewWebPanelsSidebar"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
-  list-style-image: url(chrome://mozapps/skin/places/defaultFavicon.svg);
-}
-
 #sidebar-switcher-bookmarks > .toolbarbutton-icon,
 #sidebar-box[sidebarcommand="viewBookmarksSidebar"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
   list-style-image: url(chrome://browser/skin/bookmark.svg);
   -moz-context-properties: fill;
   fill: currentColor;
   opacity: 0.8;
 }
 
index 5b8eb1145ba44f96014e20cc842d6a5079959146..ce8401109cf119e66df036c0d274b35c09e2c644
GIT binary patch
literal 65536
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
index 311ff8e25dd3077ccf235424feeb5be459997932..99670e1aa8b53b715926b041648537c8297cd7f2
GIT binary patch
literal 180224
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%0D-2{!nUbmWmGdM=&v80!SlcUJkxQSl!U~{)C
z^G!eLVgLLBcBt1A0X#r~quxlqt45q6BS3~N+LKH{ys^7Sp&YOMZ|uEeuW)M=uD5L4
zwr$(CZQHhO+t#~m`(3ted-bH*Jzv`Fq{&H}ru+I0^PbN&#xv%a4jYz@Bh|E1@>?7v
zQ!sGal+BV1Q=5z;ZL%qz7{GfUyJtWc87=wR0J`9nnrC0OQgg;j-a(|tP&dz_C#I3`
za_WG{VZv*}0w8P8Au8>|S6;RvH5{OuO8uSTt>-Q!ZigzrO}?fm_(X-}t*jV5PZV@m
zt;lG{^V|1#K?TIhp5k02A^wv=UgKt*nLVQ<T0DXg{>t7n=}5DU2?3j0#XGXYHZ0@z
zskMY9EcNj|{AK-_Z1HbqmCq}rT^W{nhgVlpR6|B49#N+9r7p=zrj$t>tr&ivw#?(o
z7NlnuyH>hRy`Bl<9dmq=1z_}rH7W!(b#k&luC<R4H~w3pUQh9%%M_1RMoSUa-N%w6
ziKMdLE8efi&_G=pQ7HAomZMJ&1&Z26%NH;F{UIrNX31_aE%pvZWbWoK84%3$>Axor
zNiM}lkXN6o<BCTwQZKFDeKT;mUXs)TjHdZE%4Fb+b_9(5ve9R__0jz4!revKi&cNR
z)&gT5x84}<Ii@TUkQk|jeMT)l^b3t8xo-k+EsXKc3<Y;(n5Iw2MXFwFw_o}TohB>J
zSdH)w6?8w%u_WUJ{BfS?S}G)&t|G30Z-p=;yXtQa4&R+Y{`dR;Ajtpf|Nr=p|M-vp
z`2Q;ZVu1X^DMoO^U=Ed=Y*UKj(=MNr35EX{pxZ8;W8i^~N&{5p`ziAx?KzjvD}#wP
zH8%*x8f5KkcbU=<ZfMhXTdxlAk^<l#?=Q+jO_8D}&JZZtSUQ-9UXFpqhfNFQ%lq{w
zTj35`q<$|j+c@JKl5h=MEK5$E9bHCd1I}l>TjQM-XwPxBH|0F#g@j5YV^i65+Gn*|
zy~qKH0IS^EpQPc|3qj|_0Ia>`CXv9O6Et*X-{wz^PsPGlgqzLn?h<(<C0CR3Vy6?4
zX!nG!Ki0~7M;u#~^Y1eL&fM)dE-(U0p=)u8ClVCKRO)!2P##!+NBl`#Z53Q}hd?$R
zS$1E~EKhLVkqADhHA+t2<!*b%_GHxtdq4kfr=U6eR-ymFnat2a2oN~|)ytP(%0AvV
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
--- a/build/pgo/server-locations.txt
+++ b/build/pgo/server-locations.txt
@@ -287,8 +287,11 @@ https://ssl3rc4.example.com:443     priv
 https://tls1.example.com:443        privileged,tls1
 
 # Hosts for youtube rewrite tests
 https://mochitest.youtube.com:443
 
 # Hosts for stylo blocklist tests
 http://stylo-blocklist.com:80          privileged
 http://test.stylo-blocklist.com:80     privileged
+
+# Host for U2F localhost tests
+https://localhost:443
--- a/devtools/client/themes/dark-theme.css
+++ b/devtools/client/themes/dark-theme.css
@@ -200,21 +200,21 @@ body {
   color: var(--theme-content-color1);
 }
 
 .cm-s-mozilla .CodeMirror-lines .CodeMirror-cursor {
   border-left: solid 1px #fff;
 }
 
 .cm-s-mozilla.CodeMirror-focused .CodeMirror-selected { /* selected text (focused) */
-  background: rgb(77, 86, 103);
+  background: var(--theme-selection-background-hover);
 }
 
 .cm-s-mozilla .CodeMirror-selected { /* selected text (unfocused) */
-  background: rgb(77, 86, 103);
+  background: var(--theme-selection-background-hover);
 }
 
 .cm-s-mozilla .CodeMirror-activeline-background { /* selected color with alpha */
   background: rgba(185, 215, 253, .15);
 }
 
 div.cm-s-mozilla span.CodeMirror-matchingbracket { /* highlight brackets */
   outline: solid 1px rgba(255, 255, 255, .25);
--- a/devtools/shared/Parser.jsm
+++ b/devtools/shared/Parser.jsm
@@ -1129,17 +1129,16 @@ var SyntaxTreeVisitor = {
 
   /**
    * A try statement.
    *
    * interface TryStatement <: Statement {
    *   type: "TryStatement";
    *   block: BlockStatement;
    *   handler: CatchClause | null;
-   *   guardedHandlers: [ CatchClause ];
    *   finalizer: BlockStatement | null;
    * }
    */
   TryStatement(node, parent, callbacks) {
     node._parent = parent;
 
     if (this.break) {
       return;
@@ -1151,19 +1150,16 @@ var SyntaxTreeVisitor = {
     }
     if (callbacks.onTryStatement) {
       callbacks.onTryStatement(node);
     }
     this[node.block.type](node.block, node, callbacks);
     if (node.handler) {
       this[node.handler.type](node.handler, node, callbacks);
     }
-    for (let guardedHandler of node.guardedHandlers) {
-      this[guardedHandler.type](guardedHandler, node, callbacks);
-    }
     if (node.finalizer) {
       this[node.finalizer.type](node.finalizer, node, callbacks);
     }
   },
 
   /**
    * A while statement.
    *
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -10526,16 +10526,19 @@ nsDocShell::InternalLoad(nsIURI* aURI,
     // LOAD_NORMAL_EXTERNAL after this point
     aLoadType = LOAD_NORMAL;
   }
 
   mAllowKeywordFixup =
     (aFlags & INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) != 0;
   mURIResultedInDocument = false;  // reset the clock...
 
+  // Note that there is code that relies on this check to stop us entering the
+  // `doShortCircuitedLoad` block below for certain load types.  (For example,
+  // reftest-content.js uses LOAD_FLAGS_BYPASS_CACHE for this purpose.)
   if (aLoadType == LOAD_NORMAL ||
       aLoadType == LOAD_STOP_CONTENT ||
       LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY) ||
       aLoadType == LOAD_HISTORY ||
       aLoadType == LOAD_LINK) {
     nsCOMPtr<nsIURI> currentURI = mCurrentURI;
 
     nsAutoCString curHash, newHash;
--- a/dom/base/DocumentFragment.h
+++ b/dom/base/DocumentFragment.h
@@ -64,43 +64,16 @@ public:
                                             nsIDOMNode::DOCUMENT_FRAGMENT_NODE)),
       mHost(nullptr)
   {
     Init();
   }
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
-  // nsIContent
-  using nsIContent::SetAttr;
-  virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
-                           nsAtom* aPrefix, const nsAString& aValue,
-                           nsIPrincipal* aSubjectPrincipal,
-                           bool aNotify) override
-  {
-    return NS_OK;
-  }
-  virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
-                             bool aNotify) override
-  {
-    return NS_OK;
-  }
-  virtual const nsAttrName* GetAttrNameAt(uint32_t aIndex) const override
-  {
-    return nullptr;
-  }
-  virtual BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const override
-  {
-    return BorrowedAttrInfo(nullptr, nullptr);
-  }
-  virtual uint32_t GetAttrCount() const override
-  {
-    return 0;
-  }
-
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override
   {
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -425,16 +425,21 @@ public:
    * Get a hint that tells the style system what to do when
    * an attribute on this node changes, if something needs to happen
    * in response to the change *other* than the result of what is
    * mapped into style data via any type of style rule.
    */
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                               int32_t aModType) const;
 
+  NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker)
+  {
+    return NS_OK;
+  }
+
   inline Directionality GetDirectionality() const {
     if (HasFlag(NODE_HAS_DIRECTION_RTL)) {
       return eDir_RTL;
     }
 
     if (HasFlag(NODE_HAS_DIRECTION_LTR)) {
       return eDir_LTR;
     }
@@ -692,18 +697,16 @@ public:
    * null otherwise.
    *
    * @param aStr the unparsed attribute string
    * @return the node info. May be nullptr.
    */
   already_AddRefed<mozilla::dom::NodeInfo>
   GetExistingAttrNameFromQName(const nsAString& aStr) const;
 
-  using nsIContent::SetAttr;
-
   /**
    * Helper for SetAttr/SetParsedAttr. This method will return true if aNotify
    * is true or there are mutation listeners that must be triggered, the
    * attribute is currently set, and the new value that is about to be set is
    * different to the current value. As a perf optimization the new and old
    * values will not actually be compared if we aren't notifying and we don't
    * have mutation listeners (in which case it's cheap to just return false
    * and let the caller go ahead and set the value).
@@ -753,57 +756,137 @@ public:
 
   /**
    * Sets the class attribute to a value that contains no whitespace.
    * Assumes that we are not notifying and that the attribute hasn't been
    * set previously.
    */
   nsresult SetSingleClassFromParser(nsAtom* aSingleClassName);
 
-  virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
-                           const nsAString& aValue, nsIPrincipal* aSubjectPrincipal,
-                           bool aNotify) override;
   // aParsedValue receives the old value of the attribute. That's useful if
   // either the input or output value of aParsedValue is StoresOwnData.
   nsresult SetParsedAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
                          nsAttrValue& aParsedValue, bool aNotify);
   // GetAttr is not inlined on purpose, to keep down codesize from all
   // the inlined nsAttrValue bits for C++ callers.
   bool GetAttr(int32_t aNameSpaceID, nsAtom* aName,
                nsAString& aResult) const;
   inline bool HasAttr(int32_t aNameSpaceID, nsAtom* aName) const;
   // aCaseSensitive == eIgnoreCaase means ASCII case-insensitive matching.
   inline bool AttrValueIs(int32_t aNameSpaceID, nsAtom* aName,
                           const nsAString& aValue,
                           nsCaseTreatment aCaseSensitive) const;
   inline bool AttrValueIs(int32_t aNameSpaceID, nsAtom* aName,
                           nsAtom* aValue,
                           nsCaseTreatment aCaseSensitive) const;
-  virtual int32_t FindAttrValueIn(int32_t aNameSpaceID,
-                                  nsAtom* aName,
-                                  AttrValuesArray* aValues,
-                                  nsCaseTreatment aCaseSensitive) const override;
-  virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
-                             bool aNotify) override;
+  int32_t FindAttrValueIn(int32_t aNameSpaceID,
+                          nsAtom* aName,
+                          AttrValuesArray* aValues,
+                          nsCaseTreatment aCaseSensitive) const override;
+
+  /**
+   * Set attribute values. All attribute values are assumed to have a
+   * canonical string representation that can be used for these
+   * methods. The SetAttr method is assumed to perform a translation
+   * of the canonical form into the underlying content specific
+   * form.
+   *
+   * @param aNameSpaceID the namespace of the attribute
+   * @param aName the name of the attribute
+   * @param aValue the value to set
+   * @param aNotify specifies how whether or not the document should be
+   *        notified of the attribute change.
+   */
+  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
+                   const nsAString& aValue, bool aNotify)
+  {
+    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
+  }
+  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
+                   const nsAString& aValue, bool aNotify)
+  {
+    return SetAttr(aNameSpaceID, aName, aPrefix, aValue, nullptr, aNotify);
+  }
+  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAString& aValue,
+                   nsIPrincipal* aTriggeringPrincipal, bool aNotify)
+  {
+    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aTriggeringPrincipal, aNotify);
+  }
 
-  virtual const nsAttrName* GetAttrNameAt(uint32_t aIndex) const final override
+  /**
+   * Set attribute values. All attribute values are assumed to have a
+   * canonical String representation that can be used for these
+   * methods. The SetAttr method is assumed to perform a translation
+   * of the canonical form into the underlying content specific
+   * form.
+   *
+   * @param aNameSpaceID the namespace of the attribute
+   * @param aName the name of the attribute
+   * @param aPrefix the prefix of the attribute
+   * @param aValue the value to set
+   * @param aMaybeScriptedPrincipal the principal of the scripted caller responsible
+   *        for setting the attribute, or null if no scripted caller can be
+   *        determined. A null value here does not guarantee that there is no
+   *        scripted caller, but a non-null value does guarantee that a scripted
+   *        caller with the given principal is directly responsible for the
+   *        attribute change.
+   * @param aNotify specifies how whether or not the document should be
+   *        notified of the attribute change.
+   */
+  virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
+                           nsAtom* aPrefix, const nsAString& aValue,
+                           nsIPrincipal* aMaybeScriptedPrincipal,
+                           bool aNotify);
+
+  /**
+   * Remove an attribute so that it is no longer explicitly specified.
+   *
+   * @param aNameSpaceID the namespace id of the attribute
+   * @param aAttr the name of the attribute to unset
+   * @param aNotify specifies whether or not the document should be
+   * notified of the attribute change
+   */
+  virtual nsresult UnsetAttr(int32_t aNameSpaceID,
+                             nsAtom* aAttribute,
+                             bool aNotify);
+
+  /**
+   * Get the namespace / name / prefix of a given attribute.
+   *
+   * @param   aIndex the index of the attribute name
+   * @returns The name at the given index, or null if the index is
+   *          out-of-bounds.
+   * @note    The document returned by NodeInfo()->GetDocument() (if one is
+   *          present) is *not* necessarily the owner document of the element.
+   * @note    The pointer returned by this function is only valid until the
+   *          next call of either GetAttrNameAt or SetAttr on the element.
+   */
+  const nsAttrName* GetAttrNameAt(uint32_t aIndex) const
   {
     return mAttrsAndChildren.GetSafeAttrNameAt(aIndex);
   }
 
-  virtual BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const final override
+  /**
+   * Gets the attribute info (name and value) for this element at a given index.
+   */
+  BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const
   {
     if (aIndex >= mAttrsAndChildren.AttrCount()) {
       return BorrowedAttrInfo(nullptr, nullptr);
     }
 
     return mAttrsAndChildren.AttrInfoAt(aIndex);
   }
 
-  virtual uint32_t GetAttrCount() const final override
+  /**
+   * Get the number of all specified attributes.
+   *
+   * @return the number of attributes
+   */
+  uint32_t GetAttrCount() const
   {
     return mAttrsAndChildren.AttrCount();
   }
 
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   /**
    * Get the class list of this element (this corresponds to the value of the
@@ -1461,17 +1544,17 @@ public:
    */
   void SetAttr(nsAtom* aAttr, const nsAString& aValue, ErrorResult& aError)
   {
     aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true);
   }
 
   void SetAttr(nsAtom* aAttr, const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
   {
-    aError = nsIContent::SetAttr(kNameSpaceID_None, aAttr, aValue, &aTriggeringPrincipal, true);
+    aError = SetAttr(kNameSpaceID_None, aAttr, aValue, &aTriggeringPrincipal, true);
   }
 
   /**
    * Set a content attribute via a reflecting nullable string IDL
    * attribute (e.g. a CORS attribute).  If DOMStringIsNull(aValue),
    * this will actually remove the content attribute.
    */
   void SetOrRemoveNullableStringAttr(nsAtom* aName, const nsAString& aValue,
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -386,31 +386,35 @@ nsIContent::LookupNamespaceURIInternal(c
   }
   else {
     name = nsGkAtoms::xmlns;
   }
   // Trace up the content parent chain looking for the namespace
   // declaration that declares aNamespacePrefix.
   const nsIContent* content = this;
   do {
-    if (content->GetAttr(kNameSpaceID_XMLNS, name, aNamespaceURI))
+    if (content->IsElement() &&
+        content->AsElement()->GetAttr(kNameSpaceID_XMLNS, name, aNamespaceURI))
       return NS_OK;
   } while ((content = content->GetParent()));
   return NS_ERROR_FAILURE;
 }
 
 nsAtom*
 nsIContent::GetLang() const
 {
   for (const auto* content = this; content; content = content->GetParent()) {
-    if (!content->GetAttrCount() || !content->IsElement()) {
+    if (!content->IsElement()) {
       continue;
     }
 
     auto* element = content->AsElement();
+    if (!element->GetAttrCount()) {
+      continue;
+    }
 
     // xml:lang has precedence over lang on HTML elements (see
     // XHTML1 section C.7).
     const nsAttrValue* attr =
       element->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
     if (!attr && element->SupportsLangAttr()) {
       attr = element->GetParsedAttr(nsGkAtoms::lang);
     }
@@ -1174,22 +1178,16 @@ bool
 nsIContent::IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse)
 {
   if (aTabIndex) {
     *aTabIndex = -1; // Default, not tabbable
   }
   return false;
 }
 
-NS_IMETHODIMP
-FragmentOrElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
-{
-  return NS_OK;
-}
-
 bool
 FragmentOrElement::IsLink(nsIURI** aURI) const
 {
   *aURI = nullptr;
   return false;
 }
 
 nsIContent*
@@ -2236,18 +2234,18 @@ FragmentOrElement::CopyInnerTo(FragmentO
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t i, count = mAttrsAndChildren.AttrCount();
   for (i = 0; i < count; ++i) {
     const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
     const nsAttrValue* value = mAttrsAndChildren.AttrAt(i);
     nsAutoString valStr;
     value->ToString(valStr);
-    rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
-                                name->GetPrefix(), valStr, false);
+    rv = aDst->AsElement()->SetAttr(name->NamespaceID(), name->LocalName(),
+                                    name->GetPrefix(), valStr, false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 const nsTextFragment*
 FragmentOrElement::GetText()
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -160,18 +160,16 @@ public:
   virtual void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot) override;
   virtual nsIContent *GetXBLInsertionPoint() const override;
   virtual void SetXBLInsertionPoint(nsIContent* aContent) override;
   virtual bool IsLink(nsIURI** aURI) const override;
 
   virtual void DestroyContent() override;
   virtual void SaveSubtreeState() override;
 
-  NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
-
   nsIHTMLCollection* Children();
   uint32_t ChildElementCount()
   {
     return Children()->Length();
   }
 
   /**
    * Sets the IsElementInStyleScope flag on each element in the subtree rooted
--- a/dom/base/nsContentCreatorFunctions.h
+++ b/dom/base/nsContentCreatorFunctions.h
@@ -58,17 +58,17 @@ NS_NewMathMLElement(mozilla::dom::Elemen
 
 #ifdef MOZ_XUL
 nsresult
 NS_NewXULElement(mozilla::dom::Element** aResult,
                  already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
                  mozilla::dom::FromParser aFromParser);
 
 void
-NS_TrustedNewXULElement(nsIContent** aResult,
+NS_TrustedNewXULElement(mozilla::dom::Element** aResult,
                         already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
 #endif
 
 nsresult
 NS_NewSVGElement(mozilla::dom::Element** aResult,
                  already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
                  mozilla::dom::FromParser aFromParser);
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -5053,23 +5053,23 @@ nsContentUtils::CreateContextualFragment
   if (content && !content->IsElement())
     content = content->GetParent();
 
   while (content && content->IsElement()) {
     nsString& tagName = *tagStack.AppendElement();
     tagName = content->NodeInfo()->QualifiedName();
 
     // see if we need to add xmlns declarations
-    uint32_t count = content->GetAttrCount();
+    uint32_t count = content->AsElement()->GetAttrCount();
     bool setDefaultNamespace = false;
     if (count > 0) {
       uint32_t index;
 
       for (index = 0; index < count; index++) {
-        const BorrowedAttrInfo info = content->GetAttrInfoAt(index);
+        const BorrowedAttrInfo info = content->AsElement()->GetAttrInfoAt(index);
         const nsAttrName* name = info.mName;
         if (name->NamespaceEquals(kNameSpaceID_XMLNS)) {
           info.mValue->ToString(uriStr);
 
           // really want something like nsXMLContentSerializer::SerializeAttr
           tagName.AppendLiteral(" xmlns"); // space important
           if (name->GetPrefix()) {
             tagName.Append(char16_t(':'));
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -416,20 +416,20 @@ nsIdentifierMapEntry::GetIdElement()
 
 Element*
 nsIdentifierMapEntry::GetImageIdElement()
 {
   return mImageElement ? mImageElement.get() : GetIdElement();
 }
 
 void
-nsIdentifierMapEntry::AppendAllIdContent(nsCOMArray<nsIContent>* aElements)
-{
-  for (size_t i = 0; i < mIdContentList.Length(); ++i) {
-    aElements->AppendObject(mIdContentList[i]);
+nsIdentifierMapEntry::AppendAllIdContent(nsCOMArray<Element>* aElements)
+{
+  for (Element* element : mIdContentList) {
+    aElements->AppendObject(element);
   }
 }
 
 void
 nsIdentifierMapEntry::AddContentChangeCallback(nsIDocument::IDTargetObserver aCallback,
                                                void* aData, bool aForImage)
 {
   if (!mChangeCallbacks) {
@@ -3771,17 +3771,21 @@ nsDocument::ElementsFromPointHelper(floa
 
   for (uint32_t i = 0; i < outFrames.Length(); i++) {
     nsIContent* node = GetContentInThisDocument(outFrames[i]);
 
     if (!node || !node->IsElement()) {
       // If this helper is called via ElementsFromPoint, we need to make sure
       // our frame is an element. Otherwise return whatever the top frame is
       // even if it isn't the top-painted element.
-      if (!(aFlags & nsIDocument::IS_ELEMENT_FROM_POINT)) {
+      // SVG 'text' element's SVGTextFrame doesn't respond to hit-testing, so
+      // if 'node' is a child of such an element then we need to manually defer
+      // to the parent here.
+      if (!(aFlags & nsIDocument::IS_ELEMENT_FROM_POINT) &&
+          !nsSVGUtils::IsInSVGTextSubtree(outFrames[i])) {
         continue;
       }
       node = node->GetParent();
     }
     if (node && node != lastAdded) {
       aElements.AppendElement(node->AsElement());
       lastAdded = node;
       // If this helper is called via ElementFromPoint, just return the first
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -632,62 +632,29 @@ nsGenericDOMDataNode::UnbindFromTree(boo
 }
 
 already_AddRefed<nsINodeList>
 nsGenericDOMDataNode::GetChildren(uint32_t aFilter)
 {
   return nullptr;
 }
 
-nsresult
-nsGenericDOMDataNode::SetAttr(int32_t aNameSpaceID, nsAtom* aAttr,
-                              nsAtom* aPrefix, const nsAString& aValue,
-                              nsIPrincipal* aContentPrincipal,
-                              bool aNotify)
-{
-  return NS_OK;
-}
-
-nsresult
-nsGenericDOMDataNode::UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttr,
-                                bool aNotify)
-{
-  return NS_OK;
-}
-
-const nsAttrName*
-nsGenericDOMDataNode::GetAttrNameAt(uint32_t aIndex) const
-{
-  return nullptr;
-}
-
-BorrowedAttrInfo
-nsGenericDOMDataNode::GetAttrInfoAt(uint32_t aIndex) const
-{
-  return BorrowedAttrInfo(nullptr, nullptr);
-}
-
-uint32_t
-nsGenericDOMDataNode::GetAttrCount() const
-{
-  return 0;
-}
-
 uint32_t
 nsGenericDOMDataNode::GetChildCount() const
 {
   return 0;
 }
 
 nsIContent *
 nsGenericDOMDataNode::GetChildAt(uint32_t aIndex) const
 {
   return nullptr;
 }
 
+
 int32_t
 nsGenericDOMDataNode::IndexOf(const nsINode* aPossibleChild) const
 {
   return -1;
 }
 
 nsresult
 nsGenericDOMDataNode::InsertChildAt(nsIContent* aKid, uint32_t aIndex,
@@ -1118,36 +1085,16 @@ nsGenericDOMDataNode::AppendTextTo(nsASt
 already_AddRefed<nsAtom>
 nsGenericDOMDataNode::GetCurrentValueAtom()
 {
   nsAutoString val;
   GetData(val);
   return NS_Atomize(val);
 }
 
-NS_IMETHODIMP
-nsGenericDOMDataNode::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP_(bool)
-nsGenericDOMDataNode::IsAttributeMapped(const nsAtom* aAttribute) const
-{
-  return false;
-}
-
-nsChangeHint
-nsGenericDOMDataNode::GetAttributeChangeHint(const nsAtom* aAttribute,
-                                             int32_t aModType) const
-{
-  NS_NOTREACHED("Shouldn't be calling this!");
-  return nsChangeHint(0);
-}
-
 void
 nsGenericDOMDataNode::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
                                              size_t* aNodeSize) const
 {
   nsIContent::AddSizeOfExcludingThis(aSizes, aNodeSize);
   *aNodeSize += mText.SizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
 }
 
--- a/dom/base/nsGenericDOMDataNode.h
+++ b/dom/base/nsGenericDOMDataNode.h
@@ -128,27 +128,16 @@ public:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) override;
 
-
-  using nsIContent::SetAttr;
-  virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
-                           nsAtom* aPrefix, const nsAString& aValue,
-                           nsIPrincipal* aSubjectPrincipal,
-                           bool aNotify) override;
-  virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
-                             bool aNotify) override;
-  virtual const nsAttrName* GetAttrNameAt(uint32_t aIndex) const override;
-  virtual mozilla::dom::BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const override;
-  virtual uint32_t GetAttrCount() const override;
   virtual const nsTextFragment *GetText() override;
   virtual uint32_t TextLength() const override;
   virtual nsresult SetText(const char16_t* aBuffer, uint32_t aLength,
                            bool aNotify) override;
   // Need to implement this here too to avoid hiding.
   nsresult SetText(const nsAString& aStr, bool aNotify)
   {
     return SetText(aStr.BeginReading(), aStr.Length(), aNotify);
@@ -179,21 +168,16 @@ public:
   virtual void SetShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot) override;
   virtual mozilla::dom::HTMLSlotElement* GetAssignedSlot() const override;
   virtual void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot) override;
   virtual nsIContent *GetXBLInsertionPoint() const override;
   virtual void SetXBLInsertionPoint(nsIContent* aContent) override;
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
   virtual bool IsLink(nsIURI** aURI) const override;
 
-  NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
-  NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const;
-  virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
-                                              int32_t aModType) const;
-
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override
   {
     nsCOMPtr<nsINode> result = CloneDataNode(aNodeInfo, true);
     result.forget(aResult);
 
     if (!*aResult) {
       return NS_ERROR_OUT_OF_MEMORY;
--- a/dom/base/nsHTMLContentSerializer.cpp
+++ b/dom/base/nsHTMLContentSerializer.cpp
@@ -59,44 +59,44 @@ nsHTMLContentSerializer::~nsHTMLContentS
 NS_IMETHODIMP
 nsHTMLContentSerializer::AppendDocumentStart(nsIDocument *aDocument,
                                              nsAString& aStr)
 {
   return NS_OK;
 }
 
 bool
-nsHTMLContentSerializer::SerializeHTMLAttributes(nsIContent* aContent,
-                                                 nsIContent *aOriginalElement,
+nsHTMLContentSerializer::SerializeHTMLAttributes(Element* aElement,
+                                                 Element* aOriginalElement,
                                                  nsAString& aTagPrefix,
                                                  const nsAString& aTagNamespaceURI,
                                                  nsAtom* aTagName,
                                                  int32_t aNamespace,
                                                  nsAString& aStr)
 {
-  int32_t count = aContent->GetAttrCount();
+  int32_t count = aElement->GetAttrCount();
   if (!count)
     return true;
 
   nsresult rv;
   nsAutoString valueStr;
   NS_NAMED_LITERAL_STRING(_mozStr, "_moz");
 
   for (int32_t index = 0; index < count; index++) {
-    const nsAttrName* name = aContent->GetAttrNameAt(index);
+    const nsAttrName* name = aElement->GetAttrNameAt(index);
     int32_t namespaceID = name->NamespaceID();
     nsAtom* 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"))) {
       continue;
     }
-    aContent->GetAttr(namespaceID, attrName, valueStr);
+    aElement->GetAttr(namespaceID, attrName, valueStr);
 
     //
     // Filter out special case of <br type="_moz"> or <br _moz*>,
     // used by the editor.  Bug 16988.  Yuck.
     //
     if (aTagName == nsGkAtoms::br && aNamespace == kNameSpaceID_XHTML &&
         attrName == nsGkAtoms::type && namespaceID == kNameSpaceID_None &&
         StringBeginsWith(valueStr, _mozStr)) {
@@ -104,45 +104,45 @@ nsHTMLContentSerializer::SerializeHTMLAt
     }
 
     if (mIsCopying && mIsFirstChildOfOL &&
         aTagName == nsGkAtoms::li && aNamespace == kNameSpaceID_XHTML &&
         attrName == nsGkAtoms::value && namespaceID == kNameSpaceID_None){
       // This is handled separately in SerializeLIValueAttribute()
       continue;
     }
-    bool isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
+    bool isJS = IsJavaScript(aElement, attrName, namespaceID, valueStr);
 
     if (((attrName == nsGkAtoms::href &&
           (namespaceID == kNameSpaceID_None ||
            namespaceID == kNameSpaceID_XLink)) ||
          (attrName == nsGkAtoms::src && namespaceID == kNameSpaceID_None))) {
       // Make all links absolute when converting only the selection:
       if (mFlags & nsIDocumentEncoder::OutputAbsoluteLinks) {
         // Would be nice to handle OBJECT tags, but that gets more complicated
         // since we have to search the tag list for CODEBASE as well. For now,
         // just leave them relative.
-        nsCOMPtr<nsIURI> uri = aContent->GetBaseURI();
+        nsCOMPtr<nsIURI> uri = aElement->GetBaseURI();
         if (uri) {
           nsAutoString absURI;
           rv = NS_MakeAbsoluteURI(absURI, valueStr, uri);
           if (NS_SUCCEEDED(rv)) {
             valueStr = absURI;
           }
         }
       }
     }
 
     if (mRewriteEncodingDeclaration && aTagName == nsGkAtoms::meta &&
         aNamespace == kNameSpaceID_XHTML && attrName == nsGkAtoms::content
         && namespaceID == kNameSpaceID_None) {
       // If we're serializing a <meta http-equiv="content-type">,
       // use the proper value, rather than what's in the document.
       nsAutoString header;
-      aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
+      aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
       if (header.LowerCaseEqualsLiteral("content-type")) {
         valueStr = NS_LITERAL_STRING("text/html; charset=") +
           NS_ConvertASCIItoUTF16(mCharset);
       }
     }
 
     nsDependentAtomString nameStr(attrName);
     nsAutoString prefix;
@@ -168,32 +168,30 @@ nsHTMLContentSerializer::SerializeHTMLAt
 
 NS_IMETHODIMP
 nsHTMLContentSerializer::AppendElementStart(Element* aElement,
                                             Element* aOriginalElement,
                                             nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
-  nsIContent* content = aElement;
-
   bool forceFormat = false;
   nsresult rv = NS_OK;
-  if (!CheckElementStart(content, forceFormat, aStr, rv)) {
+  if (!CheckElementStart(aElement, forceFormat, aStr, rv)) {
     // When we go to AppendElementEnd for this element, we're going to
     // MaybeLeaveFromPreContent().  So make sure to MaybeEnterInPreContent()
     // now, so our PreLevel() doesn't get confused.
-    MaybeEnterInPreContent(content);
+    MaybeEnterInPreContent(aElement);
     return rv;
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsAtom *name = content->NodeInfo()->NameAtom();
-  int32_t ns = content->GetNameSpaceID();
+  nsAtom *name = aElement->NodeInfo()->NameAtom();
+  int32_t ns = aElement->GetNameSpaceID();
 
   bool lineBreakBeforeOpen = LineBreakBeforeOpen(ns, name);
 
   if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
     if (mColPos && lineBreakBeforeOpen) {
       NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
     }
     else {
@@ -219,17 +217,17 @@ nsHTMLContentSerializer::AppendElementSt
   // Always reset to avoid false newlines in case MaybeAddNewlineForRootNode wasn't
   // called
   mAddNewlineForRootNode = false;
 
   NS_ENSURE_TRUE(AppendToString(kLessThan, aStr), NS_ERROR_OUT_OF_MEMORY);
 
   NS_ENSURE_TRUE(AppendToString(nsDependentAtomString(name), aStr), NS_ERROR_OUT_OF_MEMORY);
 
-  MaybeEnterInPreContent(content);
+  MaybeEnterInPreContent(aElement);
 
   // for block elements, we increase the indentation
   if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel())
     NS_ENSURE_TRUE(IncrIndentation(name), NS_ERROR_OUT_OF_MEMORY);
 
   // Need to keep track of OL and LI elements in order to get ordinal number
   // for the LI.
   if (mIsCopying && name == nsGkAtoms::ol && ns == kNameSpaceID_XHTML){
@@ -259,17 +257,17 @@ nsHTMLContentSerializer::AppendElementSt
       // If OL is parent of this LI, serialize attributes in different manner.
       NS_ENSURE_TRUE(SerializeLIValueAttribute(aElement, aStr), NS_ERROR_OUT_OF_MEMORY);
     }
   }
 
   // Even LI passed above have to go through this
   // for serializing attributes other than "value".
   nsAutoString dummyPrefix;
-  NS_ENSURE_TRUE(SerializeHTMLAttributes(content,
+  NS_ENSURE_TRUE(SerializeHTMLAttributes(aElement,
                                          aOriginalElement,
                                          dummyPrefix,
                                          EmptyString(),
                                          name,
                                          ns,
                                          aStr), NS_ERROR_OUT_OF_MEMORY);
 
   NS_ENSURE_TRUE(AppendToString(kGreaterThan, aStr), NS_ERROR_OUT_OF_MEMORY);
@@ -282,42 +280,39 @@ nsHTMLContentSerializer::AppendElementSt
     ++mDisableEntityEncoding;
   }
 
   if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel() &&
     LineBreakAfterOpen(ns, name)) {
     NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
   }
 
-  NS_ENSURE_TRUE(AfterElementStart(content, aOriginalElement, aStr), NS_ERROR_OUT_OF_MEMORY);
+  NS_ENSURE_TRUE(AfterElementStart(aElement, aOriginalElement, aStr), NS_ERROR_OUT_OF_MEMORY);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
-                                          nsAString& aStr)
+nsHTMLContentSerializer::AppendElementEnd(Element* aElement, nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
-  nsIContent* content = aElement;
-
-  nsAtom *name = content->NodeInfo()->NameAtom();
-  int32_t ns = content->GetNameSpaceID();
+  nsAtom *name = aElement->NodeInfo()->NameAtom();
+  int32_t ns = aElement->GetNameSpaceID();
 
   if (ns == kNameSpaceID_XHTML &&
       (name == nsGkAtoms::script ||
        name == nsGkAtoms::style ||
        name == nsGkAtoms::noscript ||
        name == nsGkAtoms::noframes)) {
     --mDisableEntityEncoding;
   }
 
   bool forceFormat = !(mFlags & nsIDocumentEncoder::OutputIgnoreMozDirty) &&
-                     content->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
+                     aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
 
   if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
     DecrIndentation(name);
   }
 
   if (name == nsGkAtoms::script) {
     nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aElement);
 
@@ -339,17 +334,17 @@ nsHTMLContentSerializer::AppendElementEn
   }
 
   if (ns == kNameSpaceID_XHTML) {
     bool isContainer =
       nsHTMLElement::IsContainer(nsHTMLTags::CaseSensitiveAtomTagToId(name));
     if (!isContainer) {
       // Keep this in sync with the cleanup at the end of this method.
       MOZ_ASSERT(name != nsGkAtoms::body);
-      MaybeLeaveFromPreContent(content);
+      MaybeLeaveFromPreContent(aElement);
       return NS_OK;
     }
   }
 
   if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
 
     bool lineBreakBeforeClose = LineBreakBeforeClose(ns, name);
 
@@ -371,17 +366,17 @@ nsHTMLContentSerializer::AppendElementEn
     NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
   }
 
   NS_ENSURE_TRUE(AppendToString(kEndTag, aStr), NS_ERROR_OUT_OF_MEMORY);
   NS_ENSURE_TRUE(AppendToString(nsDependentAtomString(name), aStr), NS_ERROR_OUT_OF_MEMORY);
   NS_ENSURE_TRUE(AppendToString(kGreaterThan, aStr), NS_ERROR_OUT_OF_MEMORY);
 
   // Keep this cleanup in sync with the IsContainer() early return above.
-  MaybeLeaveFromPreContent(content);
+  MaybeLeaveFromPreContent(aElement);
 
   if ((mDoFormat || forceFormat)&& !mDoRaw  && !PreLevel()
       && LineBreakAfterClose(ns, name)) {
     NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
   }
   else {
     MaybeFlagNewlineForRootNode(aElement);
   }
--- a/dom/base/nsHTMLContentSerializer.h
+++ b/dom/base/nsHTMLContentSerializer.h
@@ -12,17 +12,16 @@
 
 #ifndef nsHTMLContentSerializer_h__
 #define nsHTMLContentSerializer_h__
 
 #include "mozilla/Attributes.h"
 #include "nsXHTMLContentSerializer.h"
 #include "nsString.h"
 
-class nsIContent;
 class nsAtom;
 
 class nsHTMLContentSerializer final : public nsXHTMLContentSerializer {
  public:
   nsHTMLContentSerializer();
   virtual ~nsHTMLContentSerializer();
 
   NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement,
@@ -32,18 +31,18 @@ class nsHTMLContentSerializer final : pu
   NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
                               nsAString& aStr) override;
 
   NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
                                  nsAString& aStr) override;
  protected:
 
   MOZ_MUST_USE
-  virtual bool SerializeHTMLAttributes(nsIContent* aContent,
-                                       nsIContent *aOriginalElement,
+  virtual bool SerializeHTMLAttributes(mozilla::dom::Element* aContent,
+                                       mozilla::dom::Element* aOriginalElement,
                                        nsAString& aTagPrefix,
                                        const nsAString& aTagNamespaceURI,
                                        nsAtom* aTagName,
                                        int32_t aNamespace,
                                        nsAString& aStr);
 
   MOZ_MUST_USE
   virtual bool AppendAndTranslateEntities(const nsAString& aStr,
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -10,17 +10,16 @@
 #include "mozilla/dom/BorrowedAttrInfo.h"
 #include "nsCaseTreatment.h" // for enum, cannot be forward-declared
 #include "nsINode.h"
 #include "nsStringFwd.h"
 
 // Forward declarations
 class nsAtom;
 class nsIURI;
-class nsRuleWalker;
 class nsAttrValue;
 class nsAttrName;
 class nsTextFragment;
 class nsIFrame;
 class nsXBLBinding;
 class nsITextControlElement;
 
 namespace mozilla {
@@ -352,78 +351,26 @@ public:
 
   bool IsGeneratedContentContainerForAfter() const
   {
     return IsRootOfNativeAnonymousSubtree() &&
            mNodeInfo->NameAtom() == nsGkAtoms::mozgeneratedcontentafter;
   }
 
   /**
-   * Set attribute values. All attribute values are assumed to have a
-   * canonical string representation that can be used for these
-   * methods. The SetAttr method is assumed to perform a translation
-   * of the canonical form into the underlying content specific
-   * form.
-   *
-   * @param aNameSpaceID the namespace of the attribute
-   * @param aName the name of the attribute
-   * @param aValue the value to set
-   * @param aNotify specifies how whether or not the document should be
-   *        notified of the attribute change.
-   */
-  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
-                   const nsAString& aValue, bool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
-  }
-  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
-                   const nsAString& aValue, bool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, aPrefix, aValue, nullptr, aNotify);
-  }
-  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAString& aValue,
-                   nsIPrincipal* aTriggeringPrincipal, bool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aTriggeringPrincipal, aNotify);
-  }
-
-  /**
-   * Set attribute values. All attribute values are assumed to have a
-   * canonical String representation that can be used for these
-   * methods. The SetAttr method is assumed to perform a translation
-   * of the canonical form into the underlying content specific
-   * form.
-   *
-   * @param aNameSpaceID the namespace of the attribute
-   * @param aName the name of the attribute
-   * @param aPrefix the prefix of the attribute
-   * @param aValue the value to set
-   * @param aMaybeScriptedPrincipal the principal of the scripted caller responsible
-   *        for setting the attribute, or null if no scripted caller can be
-   *        determined. A null value here does not guarantee that there is no
-   *        scripted caller, but a non-null value does guarantee that a scripted
-   *        caller with the given principal is directly responsible for the
-   *        attribute change.
-   * @param aNotify specifies how whether or not the document should be
-   *        notified of the attribute change.
-   */
-  virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
-                           nsAtom* aPrefix, const nsAString& aValue,
-                           nsIPrincipal* aMaybeScriptedPrincipal,
-                           bool aNotify) = 0;
-
-  /**
    * Get the current value of the attribute. This returns a form that is
    * suitable for passing back into SetAttr.
    *
    * @param aNameSpaceID the namespace of the attr
    * @param aName the name of the attr
    * @param aResult the value (may legitimately be the empty string) [OUT]
    * @returns true if the attribute was set (even when set to empty string)
    *          false when not set.
+   *
+   * FIXME(emilio): Move to Element.
    */
   bool GetAttr(int32_t aNameSpaceID, nsAtom* aName,
                nsAString& aResult) const;
 
   /**
    * Determine if an attribute has been set (empty string or otherwise).
    *
    * @param aNameSpaceId the namespace id of the attribute
@@ -488,53 +435,16 @@ public:
                                   nsAtom* aName,
                                   AttrValuesArray* aValues,
                                   nsCaseTreatment aCaseSensitive) const
   {
     return ATTR_MISSING;
   }
 
   /**
-   * Remove an attribute so that it is no longer explicitly specified.
-   *
-   * @param aNameSpaceID the namespace id of the attribute
-   * @param aAttr the name of the attribute to unset
-   * @param aNotify specifies whether or not the document should be
-   * notified of the attribute change
-   */
-  virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttr,
-                             bool aNotify) = 0;
-
-
-  /**
-   * Get the namespace / name / prefix of a given attribute.
-   *
-   * @param   aIndex the index of the attribute name
-   * @returns The name at the given index, or null if the index is
-   *          out-of-bounds.
-   * @note    The document returned by NodeInfo()->GetDocument() (if one is
-   *          present) is *not* necessarily the owner document of the element.
-   * @note    The pointer returned by this function is only valid until the
-   *          next call of either GetAttrNameAt or SetAttr on the element.
-   */
-  virtual const nsAttrName* GetAttrNameAt(uint32_t aIndex) const = 0;
-
-  /**
-   * Gets the attribute info (name and value) for this content at a given index.
-   */
-  virtual mozilla::dom::BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const = 0;
-
-  /**
-   * Get the number of all specified attributes.
-   *
-   * @return the number of attributes
-   */
-  virtual uint32_t GetAttrCount() const = 0;
-
-  /**
    * Get direct access (but read only) to the text in the text content.
    * NOTE: For elements this is *not* the concatenation of all text children,
    * it is simply null;
    */
   virtual const nsTextFragment *GetText() = 0;
 
   /**
    * Get the length of the text content.
@@ -921,22 +831,16 @@ public:
   nsAtom* GetID() const {
     if (HasID()) {
       return DoGetID();
     }
     return nullptr;
   }
 
   /**
-   * Walk aRuleWalker over the content style rules (presentational
-   * hint rules) for this content node.
-   */
-  NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) = 0;
-
-  /**
    * Should be called when the node can become editable or when it can stop
    * being editable (for example when its contentEditable attribute changes,
    * when it is moved into an editable parent, ...).  If aNotify is true and
    * the node is an element, this will notify the state change.
    */
   virtual void UpdateEditableState(bool aNotify);
 
   /**
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -773,27 +773,32 @@ nsINode::LookupPrefix(const nsAString& a
   if (element) {
     // XXX Waiting for DOM spec to list error codes.
 
     // Trace up the content parent chain looking for the namespace
     // declaration that defines the aNamespaceURI namespace. Once found,
     // return the prefix (i.e. the attribute localName).
     for (nsIContent* content = element; content;
          content = content->GetParent()) {
-      uint32_t attrCount = content->GetAttrCount();
+      if (!content->IsElement()) {
+        continue;
+      }
+
+      Element* element = content->AsElement();
+      uint32_t attrCount = element->GetAttrCount();
 
       for (uint32_t i = 0; i < attrCount; ++i) {
-        const nsAttrName* name = content->GetAttrNameAt(i);
+        const nsAttrName* name = element->GetAttrNameAt(i);
 
         if (name->NamespaceEquals(kNameSpaceID_XMLNS) &&
-            content->AttrValueIs(kNameSpaceID_XMLNS, name->LocalName(),
+            element->AttrValueIs(kNameSpaceID_XMLNS, name->LocalName(),
                                  aNamespaceURI, eCaseMatters)) {
           // If the localName is "xmlns", the prefix we output should be
           // null.
-          nsAtom *localName = name->LocalName();
+          nsAtom* localName = name->LocalName();
 
           if (localName != nsGkAtoms::xmlns) {
             localName->ToString(aPrefix);
           }
           else {
             SetDOMStringToNull(aPrefix);
           }
           return;
--- a/dom/base/nsIdentifierMapEntry.h
+++ b/dom/base/nsIdentifierMapEntry.h
@@ -147,17 +147,17 @@ public:
   /**
    * If this entry has a non-null image element set (using SetImageElement),
    * the image element will be returned, otherwise the same as GetIdElement().
    */
   Element* GetImageIdElement();
   /**
    * Append all the elements with this id to aElements
    */
-  void AppendAllIdContent(nsCOMArray<nsIContent>* aElements);
+  void AppendAllIdContent(nsCOMArray<Element>* aElements);
   /**
    * This can fire ID change callbacks.
    * @return true if the content could be added, false if we failed due
    * to OOM.
    */
   bool AddIdElement(Element* aElement);
   /**
    * This can fire ID change callbacks.
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -919,24 +919,24 @@ nsObjectLoadingContent::GetNestedParams(
 nsresult
 nsObjectLoadingContent::BuildParametersArray()
 {
   if (mCachedAttributes.Length() || mCachedParameters.Length()) {
     MOZ_ASSERT(false, "Parameters array should be empty.");
     return NS_OK;
   }
 
-  nsCOMPtr<nsIContent> content =
+  nsCOMPtr<Element> element =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
-  for (uint32_t i = 0; i != content->GetAttrCount(); i += 1) {
+  for (uint32_t i = 0; i != element->GetAttrCount(); i += 1) {
     MozPluginParameter param;
-    const nsAttrName* attrName = content->GetAttrNameAt(i);
+    const nsAttrName* attrName = element->GetAttrNameAt(i);
     nsAtom* atom = attrName->LocalName();
-    content->GetAttr(attrName->NamespaceID(), atom, param.mValue);
+    element->GetAttr(attrName->NamespaceID(), atom, param.mValue);
     atom->ToString(param.mName);
     mCachedAttributes.AppendElement(param);
   }
 
   nsAutoCString wmodeOverride;
   Preferences::GetCString("plugins.force.wmode", wmodeOverride);
 
   for (uint32_t i = 0; i < mCachedAttributes.Length(); i++) {
@@ -953,20 +953,20 @@ nsObjectLoadingContent::BuildParametersA
     mCachedAttributes.AppendElement(param);
   }
 
   // Some plugins were never written to understand the "data" attribute of the OBJECT tag.
   // Real and WMP will not play unless they find a "src" attribute, see bug 152334.
   // Nav 4.x would simply replace the "data" with "src". Because some plugins correctly
   // look for "data", lets instead copy the "data" attribute and add another entry
   // to the bottom of the array if there isn't already a "src" specified.
-  if (content->IsHTMLElement(nsGkAtoms::object) &&
-      !content->HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
+  if (element->IsHTMLElement(nsGkAtoms::object) &&
+      !element->HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
     MozPluginParameter param;
-    content->GetAttr(kNameSpaceID_None, nsGkAtoms::data, param.mValue);
+    element->GetAttr(kNameSpaceID_None, nsGkAtoms::data, param.mValue);
     if (!param.mValue.IsEmpty()) {
       param.mName = NS_LITERAL_STRING("SRC");
       mCachedAttributes.AppendElement(param);
     }
   }
 
   GetNestedParams(mCachedParameters);
 
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -1396,20 +1396,22 @@ nsTreeSanitizer::SanitizeChildren(nsINod
   while (node) {
     if (node->IsElement()) {
       mozilla::dom::Element* elt = node->AsElement();
       mozilla::dom::NodeInfo* nodeInfo = node->NodeInfo();
       nsAtom* localName = nodeInfo->NameAtom();
       int32_t ns = nodeInfo->NamespaceID();
 
       if (MustPrune(ns, localName, elt)) {
-        RemoveAllAttributes(node);
+        RemoveAllAttributes(elt);
         nsIContent* descendant = node;
         while ((descendant = descendant->GetNextNode(node))) {
-          RemoveAllAttributes(descendant);
+          if (descendant->IsElement()) {
+            RemoveAllAttributes(descendant->AsElement());
+          }
         }
         nsIContent* next = node->GetNextNonChildNode(aRoot);
         node->RemoveFromParent();
         node = next;
         continue;
       }
       if (nsGkAtoms::style == localName) {
         // If styles aren't allowed, style elements got pruned above. Even
@@ -1445,17 +1447,17 @@ nsTreeSanitizer::SanitizeChildren(nsINod
                              true,
                              mAllowStyles,
                              false);
         }
         node = node->GetNextNonChildNode(aRoot);
         continue;
       }
       if (MustFlatten(ns, localName)) {
-        RemoveAllAttributes(node);
+        RemoveAllAttributes(elt);
         nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
         nsCOMPtr<nsIContent> parent = node->GetParent();
         nsCOMPtr<nsIContent> child; // Must keep the child alive during move
         ErrorResult rv;
         while ((child = node->GetFirstChild())) {
           nsCOMPtr<nsINode> refNode = node;
           parent->InsertBefore(*child, refNode, rv);
           if (rv.Failed()) {
@@ -1500,17 +1502,17 @@ nsTreeSanitizer::SanitizeChildren(nsINod
     if (!mAllowComments && node->IsNodeOfType(nsINode::eCOMMENT)) {
       node->RemoveFromParent();
     }
     node = next;
   }
 }
 
 void
-nsTreeSanitizer::RemoveAllAttributes(nsIContent* aElement)
+nsTreeSanitizer::RemoveAllAttributes(Element* aElement)
 {
   const nsAttrName* attrName;
   while ((attrName = aElement->GetAttrNameAt(0))) {
     int32_t attrNs = attrName->NamespaceID();
     RefPtr<nsAtom> attrLocal = attrName->LocalName();
     aElement->UnsetAttr(attrNs, attrLocal, false);
   }
 }
--- a/dom/base/nsTreeSanitizer.h
+++ b/dom/base/nsTreeSanitizer.h
@@ -141,18 +141,18 @@ class MOZ_STACK_CLASS nsTreeSanitizer {
      * security check.
      *
      * @param aElement the element whose attribute to possibly modify
      * @param aNamespace the namespace of the URL attribute
      * @param aLocalName the local name of the URL attribute
      * @return true if the attribute was removed and false otherwise
      */
     bool SanitizeURL(mozilla::dom::Element* aElement,
-                       int32_t aNamespace,
-                       nsAtom* aLocalName);
+                     int32_t aNamespace,
+                     nsAtom* aLocalName);
 
     /**
      * Checks a style rule for the presence of the 'binding' CSS property and
      * removes that property from the rule.
      *
      * @param aDeclaration The style declaration to check
      * @return true if the rule was modified and false otherwise
      */
@@ -173,17 +173,17 @@ class MOZ_STACK_CLASS nsTreeSanitizer {
     bool SanitizeStyleSheet(const nsAString& aOriginal,
                               nsAString& aSanitized,
                               nsIDocument* aDocument,
                               nsIURI* aBaseURI);
 
     /**
      * Removes all attributes from an element node.
      */
-    void RemoveAllAttributes(nsIContent* aElement);
+    void RemoveAllAttributes(mozilla::dom::Element* aElement);
 
     /**
      * The whitelist of HTML elements.
      */
     static nsTHashtable<nsRefPtrHashKey<nsAtom>>* sElementsHTML;
 
     /**
      * The whitelist of non-presentational HTML attributes.
--- a/dom/base/nsXHTMLContentSerializer.cpp
+++ b/dom/base/nsXHTMLContentSerializer.cpp
@@ -151,46 +151,46 @@ nsXHTMLContentSerializer::AppendText(nsI
       NS_ENSURE_TRUE(AppendToStringConvertLF(data, aStr), NS_ERROR_OUT_OF_MEMORY);
     }
   }
 
   return NS_OK;
 }
 
 bool
-nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
-                                              nsIContent *aOriginalElement,
+nsXHTMLContentSerializer::SerializeAttributes(Element* aElement,
+                                              Element* aOriginalElement,
                                               nsAString& aTagPrefix,
                                               const nsAString& aTagNamespaceURI,
                                               nsAtom* aTagName,
                                               nsAString& aStr,
                                               uint32_t aSkipAttr,
                                               bool aAddNSAttr)
 {
   nsresult rv;
   uint32_t index, count;
   nsAutoString prefixStr, uriStr, valueStr;
   nsAutoString xmlnsStr;
   xmlnsStr.AssignLiteral(kXMLNS);
 
-  int32_t contentNamespaceID = aContent->GetNameSpaceID();
+  int32_t contentNamespaceID = aElement->GetNameSpaceID();
 
   // this method is not called by nsHTMLContentSerializer
   // so we don't have to check HTML element, just XHTML
 
   if (mIsCopying && kNameSpaceID_XHTML == contentNamespaceID) {
 
     // Need to keep track of OL and LI elements in order to get ordinal number
     // for the LI.
     if (aTagName == nsGkAtoms::ol) {
       // We are copying and current node is an OL;
       // Store its start attribute value in olState->startVal.
       nsAutoString start;
       int32_t startAttrVal = 0;
-      aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::start, start);
+      aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::start, start);
       if (!start.IsEmpty()) {
         nsresult rv = NS_OK;
         startAttrVal = start.ToInteger(&rv);
         //If OL has "start" attribute, first LI element has to start with that value
         //Therefore subtracting 1 as all the LI elements are incrementing it before using it;
         //In failure of ToInteger(), default StartAttrValue to 0.
         if (NS_SUCCEEDED(rv))
           --startAttrVal;
@@ -199,17 +199,17 @@ nsXHTMLContentSerializer::SerializeAttri
       }
       olState state (startAttrVal, true);
       mOLStateStack.AppendElement(state);
     }
     else if (aTagName == nsGkAtoms::li) {
       mIsFirstChildOfOL = IsFirstChildOfOL(aOriginalElement);
       if (mIsFirstChildOfOL) {
         // If OL is parent of this LI, serialize attributes in different manner.
-        NS_ENSURE_TRUE(SerializeLIValueAttribute(aContent, aStr), false);
+        NS_ENSURE_TRUE(SerializeLIValueAttribute(aElement, aStr), false);
       }
     }
   }
 
   // If we had to add a new namespace declaration, serialize
   // and push it on the namespace stack
   if (aAddNSAttr) {
     if (aTagPrefix.IsEmpty()) {
@@ -223,28 +223,28 @@ nsXHTMLContentSerializer::SerializeAttri
                                    aTagNamespaceURI,
                                    aStr, true), false);
     }
     PushNameSpaceDecl(aTagPrefix, aTagNamespaceURI, aOriginalElement);
   }
 
   NS_NAMED_LITERAL_STRING(_mozStr, "_moz");
 
-  count = aContent->GetAttrCount();
+  count = aElement->GetAttrCount();
 
   // Now serialize each of the attributes
   // XXX Unfortunately we need a namespace manager to get
   // attribute URIs.
   for (index = 0; index < count; index++) {
 
     if (aSkipAttr == index) {
         continue;
     }
 
-    mozilla::dom::BorrowedAttrInfo info = aContent->GetAttrInfoAt(index);
+    mozilla::dom::BorrowedAttrInfo info = aElement->GetAttrInfoAt(index);
     const nsAttrName* name = info.mName;
 
     int32_t namespaceID = name->NamespaceID();
     nsAtom* attrName = name->LocalName();
     nsAtom* attrPrefix = name->GetPrefix();
 
     // Filter out any attribute starting with [-|_]moz
     nsDependentAtomString attrNameStr(attrName);
@@ -282,57 +282,57 @@ nsXHTMLContentSerializer::SerializeAttri
       }
 
       if (mIsCopying && mIsFirstChildOfOL && (aTagName == nsGkAtoms::li)
           && (attrName == nsGkAtoms::value)) {
         // This is handled separately in SerializeLIValueAttribute()
         continue;
       }
 
-      isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
+      isJS = IsJavaScript(aElement, attrName, namespaceID, valueStr);
 
       if (namespaceID == kNameSpaceID_None &&
           ((attrName == nsGkAtoms::href) ||
           (attrName == nsGkAtoms::src))) {
         // Make all links absolute when converting only the selection:
         if (mFlags & nsIDocumentEncoder::OutputAbsoluteLinks) {
           // Would be nice to handle OBJECT tags,
           // but that gets more complicated since we have to
           // search the tag list for CODEBASE as well.
           // For now, just leave them relative.
-          nsCOMPtr<nsIURI> uri = aContent->GetBaseURI();
+          nsCOMPtr<nsIURI> uri = aElement->GetBaseURI();
           if (uri) {
             nsAutoString absURI;
             rv = NS_MakeAbsoluteURI(absURI, valueStr, uri);
             if (NS_SUCCEEDED(rv)) {
               valueStr = absURI;
             }
           }
         }
       }
 
       if (mRewriteEncodingDeclaration && aTagName == nsGkAtoms::meta &&
           attrName == nsGkAtoms::content) {
         // If we're serializing a <meta http-equiv="content-type">,
         // use the proper value, rather than what's in the document.
         nsAutoString header;
-        aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
+        aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
         if (header.LowerCaseEqualsLiteral("content-type")) {
           valueStr = NS_LITERAL_STRING("text/html; charset=") +
             NS_ConvertASCIItoUTF16(mCharset);
         }
       }
 
       // Expand shorthand attribute.
       if (namespaceID == kNameSpaceID_None && IsShorthandAttr(attrName, aTagName) && valueStr.IsEmpty()) {
         valueStr = nameStr;
       }
     }
     else {
-      isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
+      isJS = IsJavaScript(aElement, attrName, namespaceID, valueStr);
     }
 
     NS_ENSURE_TRUE(SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS), false);
 
     if (addNSAttr) {
       NS_ASSERTION(!prefixStr.IsEmpty(),
                    "Namespaced attributes must have a prefix");
       NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, true), false);
@@ -409,37 +409,37 @@ nsXHTMLContentSerializer::AppendDocument
 {
   if (!mBodyOnly)
     return nsXMLContentSerializer::AppendDocumentStart(aDocument, aStr);
 
   return NS_OK;
 }
 
 bool
-nsXHTMLContentSerializer::CheckElementStart(nsIContent * aContent,
-                                            bool & aForceFormat,
+nsXHTMLContentSerializer::CheckElementStart(Element* aElement,
+                                            bool& aForceFormat,
                                             nsAString& aStr,
                                             nsresult& aResult)
 {
   aResult = NS_OK;
 
   // The _moz_dirty attribute is emitted by the editor to
   // indicate that this element should be pretty printed
   // even if we're not in pretty printing mode
   aForceFormat = !(mFlags & nsIDocumentEncoder::OutputIgnoreMozDirty) &&
-                 aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
+                 aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
 
-  if (aContent->IsHTMLElement(nsGkAtoms::br) &&
+  if (aElement->IsHTMLElement(nsGkAtoms::br) &&
       (mFlags & nsIDocumentEncoder::OutputNoFormattingInPre) &&
       PreLevel() > 0) {
     aResult = AppendNewLineToString(aStr) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     return false;
   }
 
-  if (aContent->IsHTMLElement(nsGkAtoms::body)) {
+  if (aElement->IsHTMLElement(nsGkAtoms::body)) {
     ++mInBody;
   }
 
   return true;
 }
 
 bool
 nsXHTMLContentSerializer::CheckElementEnd(mozilla::dom::Element* aElement,
@@ -829,17 +829,17 @@ nsXHTMLContentSerializer::IsFirstChildOf
 
     return false;
   }
   else
     return false;
 }
 
 bool
-nsXHTMLContentSerializer::HasNoChildren(nsIContent * aContent) {
+nsXHTMLContentSerializer::HasNoChildren(nsIContent* aContent) {
 
   for (nsIContent* child = aContent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
 
     if (!child->IsNodeOfType(nsINode::eTEXT))
       return false;
 
--- a/dom/base/nsXHTMLContentSerializer.h
+++ b/dom/base/nsXHTMLContentSerializer.h
@@ -43,20 +43,20 @@ class nsXHTMLContentSerializer : public 
                         nsAString& aStr) override;
 
   NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
                                  nsAString& aStr) override;
 
  protected:
 
 
-  virtual bool CheckElementStart(nsIContent * aContent,
-                          bool & aForceFormat,
-                          nsAString& aStr,
-                          nsresult& aResult) override;
+  virtual bool CheckElementStart(mozilla::dom::Element* aElement,
+                                 bool& aForceFormat,
+                                 nsAString& aStr,
+                                 nsresult& aResult) override;
 
   MOZ_MUST_USE
   virtual bool AfterElementStart(nsIContent* aContent,
                                  nsIContent* aOriginalElement,
                                  nsAString& aStr) override;
 
   virtual bool CheckElementEnd(mozilla::dom::Element* aContent,
                                bool& aForceFormat,
@@ -72,24 +72,24 @@ class nsXHTMLContentSerializer : public 
 
   bool HasLongLines(const nsString& text, int32_t& aLastNewlineOffset);
 
   // functions to check if we enter in or leave from a preformated content
   virtual void MaybeEnterInPreContent(nsIContent* aNode) override;
   virtual void MaybeLeaveFromPreContent(nsIContent* aNode) override;
 
   MOZ_MUST_USE
-  virtual bool SerializeAttributes(nsIContent* aContent,
-                           nsIContent *aOriginalElement,
-                           nsAString& aTagPrefix,
-                           const nsAString& aTagNamespaceURI,
-                           nsAtom* aTagName,
-                           nsAString& aStr,
-                           uint32_t aSkipAttr,
-                           bool aAddNSAttr) override;
+  virtual bool SerializeAttributes(mozilla::dom::Element* aContent,
+                                   mozilla::dom::Element* aOriginalElement,
+                                   nsAString& aTagPrefix,
+                                   const nsAString& aTagNamespaceURI,
+                                   nsAtom* aTagName,
+                                   nsAString& aStr,
+                                   uint32_t aSkipAttr,
+                                   bool aAddNSAttr) override;
 
   bool IsFirstChildOfOL(nsIContent* aElement);
 
   MOZ_MUST_USE
   bool SerializeLIValueAttribute(nsIContent* aElement,
                                  nsAString& aStr);
   bool IsShorthandAttr(const nsAtom* aAttrName,
                          const nsAtom* aElementName);
--- a/dom/base/nsXMLContentSerializer.cpp
+++ b/dom/base/nsXMLContentSerializer.cpp
@@ -707,30 +707,30 @@ nsXMLContentSerializer::SerializeAttr(co
   else {
     NS_ENSURE_TRUE(AppendToStringConvertLF(attrString, aStr), false);
   }
 
   return true;
 }
 
 uint32_t
-nsXMLContentSerializer::ScanNamespaceDeclarations(nsIContent* aContent,
-                                                  nsIContent *aOriginalElement,
+nsXMLContentSerializer::ScanNamespaceDeclarations(Element* aElement,
+                                                  Element* aOriginalElement,
                                                   const nsAString& aTagNamespaceURI)
 {
   uint32_t index, count;
   nsAutoString uriStr, valueStr;
 
-  count = aContent->GetAttrCount();
+  count = aElement->GetAttrCount();
 
   // First scan for namespace declarations, pushing each on the stack
   uint32_t skipAttr = count;
   for (index = 0; index < count; index++) {
 
-    const BorrowedAttrInfo info = aContent->GetAttrInfoAt(index);
+    const BorrowedAttrInfo info = aElement->GetAttrInfoAt(index);
     const nsAttrName* name = info.mName;
 
     int32_t namespaceID = name->NamespaceID();
     nsAtom *attrName = name->LocalName();
 
     if (namespaceID == kNameSpaceID_XMLNS ||
         // Also push on the stack attrs named "xmlns" in the null
         // namespace... because once we serialize those out they'll look like
@@ -794,18 +794,18 @@ nsXMLContentSerializer::IsJavaScript(nsI
       return false;
   }
 
   return aContent->IsEventAttributeName(aAttrNameAtom);
 }
 
 
 bool
-nsXMLContentSerializer::SerializeAttributes(nsIContent* aContent,
-                                            nsIContent *aOriginalElement,
+nsXMLContentSerializer::SerializeAttributes(Element* aElement,
+                                            Element* aOriginalElement,
                                             nsAString& aTagPrefix,
                                             const nsAString& aTagNamespaceURI,
                                             nsAtom* aTagName,
                                             nsAString& aStr,
                                             uint32_t aSkipAttr,
                                             bool aAddNSAttr)
 {
 
@@ -823,27 +823,27 @@ nsXMLContentSerializer::SerializeAttribu
     }
     else {
       // Serialize namespace decl
       NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, aTagPrefix, aTagNamespaceURI, aStr, true), false);
     }
     PushNameSpaceDecl(aTagPrefix, aTagNamespaceURI, aOriginalElement);
   }
 
-  count = aContent->GetAttrCount();
+  count = aElement->GetAttrCount();
 
   // Now serialize each of the attributes
   // XXX Unfortunately we need a namespace manager to get
   // attribute URIs.
   for (index = 0; index < count; index++) {
     if (aSkipAttr == index) {
         continue;
     }
 
-    const nsAttrName* name = aContent->GetAttrNameAt(index);
+    const nsAttrName* name = aElement->GetAttrNameAt(index);
     int32_t namespaceID = name->NamespaceID();
     nsAtom* attrName = name->LocalName();
     nsAtom* attrPrefix = name->GetPrefix();
 
     // Filter out any attribute starting with [-|_]moz
     nsDependentAtomString attrNameStr(attrName);
     if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
         StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
@@ -858,20 +858,20 @@ nsXMLContentSerializer::SerializeAttribu
     }
 
     bool addNSAttr = false;
     if (kNameSpaceID_XMLNS != namespaceID) {
       nsContentUtils::NameSpaceManager()->GetNameSpaceURI(namespaceID, uriStr);
       addNSAttr = ConfirmPrefix(prefixStr, uriStr, aOriginalElement, true);
     }
 
-    aContent->GetAttr(namespaceID, attrName, valueStr);
+    aElement->GetAttr(namespaceID, attrName, valueStr);
 
     nsDependentAtomString nameStr(attrName);
-    bool isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
+    bool isJS = IsJavaScript(aElement, attrName, namespaceID, valueStr);
 
     NS_ENSURE_TRUE(SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS), false);
 
     if (addNSAttr) {
       NS_ASSERTION(!prefixStr.IsEmpty(),
                    "Namespaced attributes must have a prefix");
       NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, true), false);
       PushNameSpaceDecl(prefixStr, uriStr, aOriginalElement);
@@ -883,40 +883,39 @@ nsXMLContentSerializer::SerializeAttribu
 
 NS_IMETHODIMP
 nsXMLContentSerializer::AppendElementStart(Element* aElement,
                                            Element* aOriginalElement,
                                            nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
-  nsIContent* content = aElement;
-
   bool forceFormat = false;
   nsresult rv = NS_OK;
-  if (!CheckElementStart(content, forceFormat, aStr, rv)) {
+  if (!CheckElementStart(aElement, forceFormat, aStr, rv)) {
     // When we go to AppendElementEnd for this element, we're going to
     // MaybeLeaveFromPreContent().  So make sure to MaybeEnterInPreContent()
     // now, so our PreLevel() doesn't get confused.
-    MaybeEnterInPreContent(content);
+    MaybeEnterInPreContent(aElement);
     return rv;
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
   aElement->NodeInfo()->GetPrefix(tagPrefix);
   aElement->NodeInfo()->GetName(tagLocalName);
   aElement->NodeInfo()->GetNamespaceURI(tagNamespaceURI);
 
-  uint32_t skipAttr = ScanNamespaceDeclarations(content,
-                          aOriginalElement, tagNamespaceURI);
+  uint32_t skipAttr =
+    ScanNamespaceDeclarations(aElement, aOriginalElement, tagNamespaceURI);
 
-  nsAtom *name = content->NodeInfo()->NameAtom();
-  bool lineBreakBeforeOpen = LineBreakBeforeOpen(content->GetNameSpaceID(), name);
+  nsAtom *name = aElement->NodeInfo()->NameAtom();
+  bool lineBreakBeforeOpen =
+    LineBreakBeforeOpen(aElement->GetNameSpaceID(), name);
 
   if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
     if (mColPos && lineBreakBeforeOpen) {
       NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
     }
     else {
       NS_ENSURE_TRUE(MaybeAddNewlineForRootNode(aStr), NS_ERROR_OUT_OF_MEMORY);
     }
@@ -947,35 +946,36 @@ nsXMLContentSerializer::AppendElementSta
   // Serialize the qualified name of the element
   NS_ENSURE_TRUE(AppendToString(kLessThan, aStr), NS_ERROR_OUT_OF_MEMORY);
   if (!tagPrefix.IsEmpty()) {
     NS_ENSURE_TRUE(AppendToString(tagPrefix, aStr), NS_ERROR_OUT_OF_MEMORY);
     NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING(":"), aStr), NS_ERROR_OUT_OF_MEMORY);
   }
   NS_ENSURE_TRUE(AppendToString(tagLocalName, aStr), NS_ERROR_OUT_OF_MEMORY);
 
-  MaybeEnterInPreContent(content);
+  MaybeEnterInPreContent(aElement);
 
   if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
     NS_ENSURE_TRUE(IncrIndentation(name), NS_ERROR_OUT_OF_MEMORY);
   }
 
-  NS_ENSURE_TRUE(SerializeAttributes(content, aOriginalElement, tagPrefix, tagNamespaceURI,
-                                     name, aStr, skipAttr, addNSAttr),
+  NS_ENSURE_TRUE(SerializeAttributes(aElement, aOriginalElement, tagPrefix,
+                                     tagNamespaceURI, name, aStr, skipAttr,
+                                     addNSAttr),
                  NS_ERROR_OUT_OF_MEMORY);
 
   NS_ENSURE_TRUE(AppendEndOfElementStart(aElement, aOriginalElement, aStr),
                  NS_ERROR_OUT_OF_MEMORY);
 
   if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()
-    && LineBreakAfterOpen(content->GetNameSpaceID(), name)) {
+    && LineBreakAfterOpen(aElement->GetNameSpaceID(), name)) {
     NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
   }
 
-  NS_ENSURE_TRUE(AfterElementStart(content, aOriginalElement, aStr), NS_ERROR_OUT_OF_MEMORY);
+  NS_ENSURE_TRUE(AfterElementStart(aElement, aOriginalElement, aStr), NS_ERROR_OUT_OF_MEMORY);
 
   return NS_OK;
 }
 
 // aElement is the actual element we're outputting.  aOriginalElement is the one
 // in the original DOM, which is the one we have to test for kids.
 static bool
 ElementNeedsSeparateEndTag(Element* aElement, Element* aOriginalElement)
@@ -1140,18 +1140,18 @@ nsXMLContentSerializer::AppendDocumentSt
 
   NS_ENSURE_TRUE(aStr.AppendLiteral("?>", mozilla::fallible), NS_ERROR_OUT_OF_MEMORY);
   mAddNewlineForRootNode = true;
 
   return NS_OK;
 }
 
 bool
-nsXMLContentSerializer::CheckElementStart(nsIContent * aContent,
-                                          bool & aForceFormat,
+nsXMLContentSerializer::CheckElementStart(Element*,
+                                          bool& aForceFormat,
                                           nsAString& aStr,
                                           nsresult& aResult)
 {
   aResult = NS_OK;
   aForceFormat = false;
   return true;
 }
 
--- a/dom/base/nsXMLContentSerializer.h
+++ b/dom/base/nsXMLContentSerializer.h
@@ -204,23 +204,23 @@ class nsXMLContentSerializer : public ns
                        const nsAString& aURI,
                        nsIContent* aElement,
                        bool aIsAttribute);
   /**
    * GenerateNewPrefix generates a new prefix and writes it to aPrefix
    */
   void GenerateNewPrefix(nsAString& aPrefix);
 
-  uint32_t ScanNamespaceDeclarations(nsIContent* aContent,
-                                     nsIContent *aOriginalElement,
+  uint32_t ScanNamespaceDeclarations(mozilla::dom::Element* aContent,
+                                     mozilla::dom::Element* aOriginalElement,
                                      const nsAString& aTagNamespaceURI);
 
   MOZ_MUST_USE
-  virtual bool SerializeAttributes(nsIContent* aContent,
-                                   nsIContent *aOriginalElement,
+  virtual bool SerializeAttributes(mozilla::dom::Element* aContent,
+                                   mozilla::dom::Element* aOriginalElement,
                                    nsAString& aTagPrefix,
                                    const nsAString& aTagNamespaceURI,
                                    nsAtom* aTagName,
                                    nsAString& aStr,
                                    uint32_t aSkipAttr,
                                    bool aAddNSAttr);
 
   MOZ_MUST_USE
@@ -238,20 +238,20 @@ class nsXMLContentSerializer : public ns
   /**
    * This method can be redefined to check if the element can be serialized.
    * It is called when the serialization of the start tag is asked
    * (AppendElementStart)
    * In this method you can also force the formating
    * by setting aForceFormat to true.
    * @return boolean  true if the element can be output
    */
-  virtual bool CheckElementStart(nsIContent * aContent,
-                                   bool & aForceFormat,
-                                   nsAString& aStr,
-                                   nsresult& aResult);
+  virtual bool CheckElementStart(Element* aElement,
+                                 bool & aForceFormat,
+                                 nsAString& aStr,
+                                 nsresult& aResult);
 
   /**
    * This method is responsible for appending the '>' at the end of the start
    * tag, possibly preceded by '/' and maybe a ' ' before that too.
    *
    * aElement and aOriginalElement are the same as the corresponding arguments
    * to AppendElementStart.
    */
--- a/dom/file/nsHostObjectProtocolHandler.cpp
+++ b/dom/file/nsHostObjectProtocolHandler.cpp
@@ -489,17 +489,18 @@ public:
     return NS_OK;
   }
 
   // nsIAsyncShutdownBlocker interface
 
   NS_IMETHOD
   GetName(nsAString& aName) override
   {
-    aName.AssignLiteral("ReleasingTimerHolder");
+    aName.AssignLiteral("ReleasingTimerHolder for blobURL: ");
+    aName.Append(NS_ConvertUTF8toUTF16(mURI));
     return NS_OK;
   }
 
   NS_IMETHOD
   BlockShutdown(nsIAsyncShutdownClient* aClient) override
   {
     CancelTimerAndRevokeURI();
     return NS_OK;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -4586,21 +4586,28 @@ ContentParent::CommonCreateWindow(PBrows
                                               aNextTabParentId, aName,
                                               getter_AddRefs(frameLoaderOwner));
     }
     if (NS_SUCCEEDED(aResult) && frameLoaderOwner) {
       RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
       if (frameLoader) {
         frameLoader->GetTabParent(getter_AddRefs(aNewTabParent));
       }
+    } else if (NS_SUCCEEDED(aResult) && !frameLoaderOwner) {
+      // Fall through to the normal window opening code path when there is no
+      // window which we can open a new tab in.
+      openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW;
     } else {
       *aWindowIsNew = false;
     }
 
-    return IPC_OK();
+    // If we didn't retarget our window open into a new window, we should return now.
+    if (openLocation != nsIBrowserDOMWindow::OPEN_NEWWINDOW) {
+      return IPC_OK();
+    }
   }
 
   nsCOMPtr<nsPIWindowWatcher> pwwatch =
     do_GetService(NS_WINDOWWATCHER_CONTRACTID, &aResult);
   if (NS_WARN_IF(NS_FAILED(aResult))) {
     return IPC_OK();
   }
 
--- a/dom/media/AudioSegment.h
+++ b/dom/media/AudioSegment.h
@@ -182,17 +182,19 @@ struct AudioChunk {
         if (aOther.mChannelData[channel] != AddAudioSampleOffset(mChannelData[channel],
             mBufferFormat, int32_t(mDuration))) {
           return false;
         }
       }
     }
     return true;
   }
-  bool IsNull() const { return mBuffer == nullptr; }
+  bool IsNull() const {
+    return mBuffer == nullptr;
+  }
   void SetNull(StreamTime aDuration)
   {
     mBuffer = nullptr;
     mChannelData.Clear();
     mDuration = aDuration;
     mVolume = 1.0f;
     mBufferFormat = AUDIO_FORMAT_SILENCE;
     mPrincipalHandle = PRINCIPAL_HANDLE_NONE;
@@ -328,54 +330,63 @@ public:
       }
       mDuration += c.mDuration;
     }
   }
 
   void ResampleChunks(SpeexResamplerState* aResampler,
                       uint32_t aInRate,
                       uint32_t aOutRate);
-
   void AppendFrames(already_AddRefed<ThreadSharedObject> aBuffer,
                     const nsTArray<const float*>& aChannelData,
                     int32_t aDuration, const PrincipalHandle& aPrincipalHandle)
   {
     AudioChunk* chunk = AppendChunk(aDuration);
     chunk->mBuffer = aBuffer;
+
+    MOZ_ASSERT(chunk->mBuffer || aChannelData.IsEmpty(), "Appending invalid data ?");
+
     for (uint32_t channel = 0; channel < aChannelData.Length(); ++channel) {
       chunk->mChannelData.AppendElement(aChannelData[channel]);
     }
     chunk->mBufferFormat = AUDIO_FORMAT_FLOAT32;
 #ifdef MOZILLA_INTERNAL_API
     chunk->mTimeStamp = TimeStamp::Now();
 #endif
     chunk->mPrincipalHandle = aPrincipalHandle;
   }
   void AppendFrames(already_AddRefed<ThreadSharedObject> aBuffer,
                     const nsTArray<const int16_t*>& aChannelData,
                     int32_t aDuration, const PrincipalHandle& aPrincipalHandle)
   {
     AudioChunk* chunk = AppendChunk(aDuration);
     chunk->mBuffer = aBuffer;
+
+    MOZ_ASSERT(chunk->mBuffer || aChannelData.IsEmpty(), "Appending invalid data ?");
+
     for (uint32_t channel = 0; channel < aChannelData.Length(); ++channel) {
       chunk->mChannelData.AppendElement(aChannelData[channel]);
     }
     chunk->mBufferFormat = AUDIO_FORMAT_S16;
 #ifdef MOZILLA_INTERNAL_API
     chunk->mTimeStamp = TimeStamp::Now();
 #endif
     chunk->mPrincipalHandle = aPrincipalHandle;
+
   }
   // Consumes aChunk, and returns a pointer to the persistent copy of aChunk
   // in the segment.
   AudioChunk* AppendAndConsumeChunk(AudioChunk* aChunk)
   {
     AudioChunk* chunk = AppendChunk(aChunk->mDuration);
     chunk->mBuffer = aChunk->mBuffer.forget();
     chunk->mChannelData.SwapElements(aChunk->mChannelData);
+
+    MOZ_ASSERT(chunk->mBuffer || aChunk->mChannelData.IsEmpty(), "Appending invalid data ?");
+
     chunk->mVolume = aChunk->mVolume;
     chunk->mBufferFormat = aChunk->mBufferFormat;
 #ifdef MOZILLA_INTERNAL_API
     chunk->mTimeStamp = TimeStamp::Now();
 #endif
     chunk->mPrincipalHandle = aChunk->mPrincipalHandle;
     return chunk;
   }
--- a/dom/media/StreamTracks.h
+++ b/dom/media/StreamTracks.h
@@ -11,27 +11,27 @@
 #include "TrackID.h"
 
 namespace mozilla {
 
 inline TrackTicks RateConvertTicksRoundDown(TrackRate aOutRate,
                                             TrackRate aInRate,
                                             TrackTicks aTicks)
 {
-  NS_ASSERTION(0 < aOutRate && aOutRate <= TRACK_RATE_MAX, "Bad out rate");
-  NS_ASSERTION(0 < aInRate && aInRate <= TRACK_RATE_MAX, "Bad in rate");
-  NS_ASSERTION(0 <= aTicks && aTicks <= TRACK_TICKS_MAX, "Bad ticks");
+  MOZ_ASSERT(0 < aOutRate && aOutRate <= TRACK_RATE_MAX, "Bad out rate");
+  MOZ_ASSERT(0 < aInRate && aInRate <= TRACK_RATE_MAX, "Bad in rate");
+  MOZ_ASSERT(0 <= aTicks && aTicks <= TRACK_TICKS_MAX, "Bad ticks");
   return (aTicks * aOutRate) / aInRate;
 }
 inline TrackTicks RateConvertTicksRoundUp(TrackRate aOutRate,
                                           TrackRate aInRate, TrackTicks aTicks)
 {
-  NS_ASSERTION(0 < aOutRate && aOutRate <= TRACK_RATE_MAX, "Bad out rate");
-  NS_ASSERTION(0 < aInRate && aInRate <= TRACK_RATE_MAX, "Bad in rate");
-  NS_ASSERTION(0 <= aTicks && aTicks <= TRACK_TICKS_MAX, "Bad ticks");
+  MOZ_ASSERT(0 < aOutRate && aOutRate <= TRACK_RATE_MAX, "Bad out rate");
+  MOZ_ASSERT(0 < aInRate && aInRate <= TRACK_RATE_MAX, "Bad in rate");
+  MOZ_ASSERT(0 <= aTicks && aTicks <= TRACK_TICKS_MAX, "Bad ticks");
   return (aTicks * aOutRate + aInRate - 1) / aInRate;
 }
 
 /**
  * This object contains the decoded data for a stream's tracks.
  * A StreamTracks can be appended to. Logically a StreamTracks only gets longer,
  * but we also have the ability to "forget" data before a certain time that
  * we know won't be used again. (We prune a whole number of seconds internally.)
--- a/dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_audio.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_audio.html
@@ -11,17 +11,17 @@ createHTML({
   bug: "1259788",
   title: "Test CaptureStream audio content on HTMLMediaElement playing a gUM MediaStream",
   visible: true
 });
 
 var audioContext;
 var gUMAudioElement;
 var analyser;
-runTest(() => getUserMedia({audio: true})
+runTest(() => getUserMedia({audio: { echoCancellation: false }})
   .then(stream => {
     gUMAudioElement = createMediaElement("audio", "gUMAudio");
     gUMAudioElement.srcObject = stream;
 
     audioContext = new AudioContext();
     info("Capturing");
 
     analyser = new AudioStreamAnalyser(audioContext,
--- a/dom/media/tests/mochitest/test_peerConnection_transceivers.html
+++ b/dom/media/tests/mochitest/test_peerConnection_transceivers.html
@@ -418,21 +418,22 @@
   };
 
   let checkAddTransceiverBadKind = async () => {
     let pc = new RTCPeerConnection();
     try {
       pc.addTransceiver("foo");
       ok(false, 'addTransceiver("foo") throws');
     }
-    catch (e if e instanceof TypeError) {
-      ok(true, 'addTransceiver("foo") throws a TypeError');
-    }
     catch (e) {
-      ok(false, 'addTransceiver("foo") throws a TypeError');
+      if (e instanceof TypeError) {
+        ok(true, 'addTransceiver("foo") throws a TypeError');
+      } else {
+        ok(false, 'addTransceiver("foo") throws a TypeError');
+      }
     }
 
     hasProps(pc.getTransceivers(), []);
 
     pc.close();
   };
 
   let checkAddTransceiverNoTrackDoesntPair = async () => {
--- a/dom/media/webrtc/AudioOutputObserver.h
+++ b/dom/media/webrtc/AudioOutputObserver.h
@@ -12,23 +12,23 @@
 
 namespace webrtc {
 class SingleRwFifo;
 }
 
 namespace mozilla {
 
 typedef struct FarEndAudioChunk_ {
-  uint16_t mSamples;
+  size_t mSamples;
   bool mOverrun;
-  int16_t mData[1]; // variable-length
+  AudioDataValue mData[1]; // variable-length
 } FarEndAudioChunk;
 
 // This class is used to packetize and send the mixed audio from an MSG, in
-// int16, to the AEC module of WebRTC.org.
+// float, to the AEC module of WebRTC.org.
 class AudioOutputObserver
 {
 public:
   AudioOutputObserver();
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AudioOutputObserver);
 
   void Clear();
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -48,18 +48,16 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEngine)
 
   static const int DEFAULT_VIDEO_FPS = 30;
   static const int DEFAULT_43_VIDEO_WIDTH = 640;
   static const int DEFAULT_43_VIDEO_HEIGHT = 480;
   static const int DEFAULT_169_VIDEO_WIDTH = 1280;
   static const int DEFAULT_169_VIDEO_HEIGHT = 720;
 
-  static const int DEFAULT_SAMPLE_RATE = 32000;
-
   // This allows using whatever rate the graph is using for the
   // MediaStreamTrack. This is useful for microphone data, we know it's already
   // at the correct rate for insertion in the MSG.
   static const int USE_GRAPH_RATE = -1;
 
   /* Populate an array of video sources in the nsTArray. Also include devices
    * that are currently unavailable. */
   virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -21,17 +21,16 @@
 #ifdef MOZ_WIDGET_ANDROID
 #include "nsISupportsUtils.h"
 #endif
 
 #ifdef MOZ_WEBRTC
 #include "YuvStamper.h"
 #endif
 
-#define AUDIO_RATE mozilla::MediaEngine::DEFAULT_SAMPLE_RATE
 #define DEFAULT_AUDIO_TIMER_MS 10
 namespace mozilla {
 
 using namespace mozilla::gfx;
 
 NS_IMPL_ISUPPORTS(MediaEngineDefaultVideoSource, nsITimerCallback, nsINamed)
 /**
  * Default video source.
@@ -327,16 +326,17 @@ MediaEngineDefaultVideoSource::NotifyPul
  * Default audio source.
  */
 
 NS_IMPL_ISUPPORTS0(MediaEngineDefaultAudioSource)
 
 MediaEngineDefaultAudioSource::MediaEngineDefaultAudioSource()
   : MediaEngineAudioSource(kReleased)
   , mLastNotify(0)
+  , mFreq(1000)
 {}
 
 MediaEngineDefaultAudioSource::~MediaEngineDefaultAudioSource()
 {}
 
 void
 MediaEngineDefaultAudioSource::GetName(nsAString& aName) const
 {
@@ -377,20 +377,18 @@ MediaEngineDefaultAudioSource::Allocate(
   }
 
   // Mock failure for automated tests.
   if (aConstraints.mDeviceId.IsString() &&
       aConstraints.mDeviceId.GetAsString().EqualsASCII("bad device")) {
     return NS_ERROR_FAILURE;
   }
 
+  mFreq = aPrefs.mFreq ? aPrefs.mFreq : 1000;
   mState = kAllocated;
-  // generate sine wave (default 1KHz)
-  mSineGenerator = new SineWaveGenerator(AUDIO_RATE,
-                                         static_cast<uint32_t>(aPrefs.mFreq ? aPrefs.mFreq : 1000));
   *aOutHandle = nullptr;
   return NS_OK;
 }
 
 nsresult
 MediaEngineDefaultAudioSource::Deallocate(AllocationHandle* aHandle)
 {
   MOZ_ASSERT(!aHandle);
@@ -404,19 +402,25 @@ MediaEngineDefaultAudioSource::Deallocat
 nsresult
 MediaEngineDefaultAudioSource::Start(SourceMediaStream* aStream, TrackID aID,
                                      const PrincipalHandle& aPrincipalHandle)
 {
   if (mState != kAllocated) {
     return NS_ERROR_FAILURE;
   }
 
+
+  if (!mSineGenerator) {
+    // generate sine wave (default 1KHz)
+    mSineGenerator = new SineWaveGenerator(aStream->GraphRate(), mFreq);
+  }
+
   // AddTrack will take ownership of segment
   AudioSegment* segment = new AudioSegment();
-  aStream->AddAudioTrack(aID, AUDIO_RATE, 0, segment, SourceMediaStream::ADDTRACK_QUEUED);
+  aStream->AddAudioTrack(aID, aStream->GraphRate(), 0, segment, SourceMediaStream::ADDTRACK_QUEUED);
 
   // Remember TrackID so we can finish later
   mTrackID = aID;
 
   mLastNotify = 0;
   mState = kStarted;
   return NS_OK;
 }
@@ -462,17 +466,17 @@ MediaEngineDefaultAudioSource::NotifyPul
                                           SourceMediaStream *aSource,
                                           TrackID aID,
                                           StreamTime aDesiredTime,
                                           const PrincipalHandle& aPrincipalHandle)
 {
   MOZ_ASSERT(aID == mTrackID);
   AudioSegment segment;
   // avoid accumulating rounding errors
-  TrackTicks desired = aSource->TimeToTicksRoundUp(AUDIO_RATE, aDesiredTime);
+  TrackTicks desired = aSource->TimeToTicksRoundUp(aGraph->GraphRate(), aDesiredTime);
   TrackTicks delta = desired - mLastNotify;
   mLastNotify += delta;
   AppendToSegment(segment, delta, aPrincipalHandle);
   aSource->AppendToTrack(mTrackID, &segment);
 }
 
 void
 MediaEngineDefault::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
--- a/dom/media/webrtc/MediaEngineDefault.h
+++ b/dom/media/webrtc/MediaEngineDefault.h
@@ -183,18 +183,19 @@ public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
 protected:
   ~MediaEngineDefaultAudioSource();
 
   TrackID mTrackID;
 
   TrackTicks mLastNotify; // Accessed in ::Start(), then on NotifyPull (from MSG thread)
+  uint32_t mFreq; // ditto
 
-  // Created on Allocate, then accessed from NotifyPull (MSG thread)
+  // Created on Start, then accessed from NotifyPull (MSG thread)
   nsAutoPtr<SineWaveGenerator> mSineGenerator;
 };
 
 
 class MediaEngineDefault : public MediaEngine
 {
   typedef MediaEngine Super;
 public:
--- a/dom/media/webrtc/MediaEngineWebRTC.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTC.cpp
@@ -102,17 +102,16 @@ void AudioInputCubeb::UpdateDeviceList()
   StaticMutexAutoLock lock(sMutex);
   // swap state
   cubeb_device_collection_destroy(cubebContext, &mDevices);
   mDevices = devices;
 }
 
 MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs)
   : mMutex("mozilla::MediaEngineWebRTC"),
-    mVoiceEngine(nullptr),
     mAudioInput(nullptr),
     mFullDuplex(aPrefs.mFullDuplex),
     mDelayAgnostic(aPrefs.mDelayAgnostic),
     mExtendedFilter(aPrefs.mExtendedFilter),
     mHasTabVideoSource(false)
 {
   nsCOMPtr<nsIComponentRegistrar> compMgr;
   NS_GetComponentRegistrar(getter_AddRefs(compMgr));
@@ -275,53 +274,21 @@ MediaEngineWebRTC::EnumerateAudioDevices
 
   if (aMediaSource == dom::MediaSourceEnum::AudioCapture) {
     RefPtr<MediaEngineWebRTCAudioCaptureSource> audioCaptureSource =
       new MediaEngineWebRTCAudioCaptureSource(nullptr);
     aASources->AppendElement(audioCaptureSource);
     return;
   }
 
-#ifdef MOZ_WIDGET_ANDROID
-  JavaVM* jvm = mozilla::jni::GetVM();
-  jobject context = mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
-
-  if (webrtc::VoiceEngine::SetAndroidObjects(jvm, (void*)context) != 0) {
-    LOG(("VoiceEngine:SetAndroidObjects Failed"));
-    return;
-  }
-#endif
-
-  if (!mVoiceEngine) {
-    mVoiceEngine = webrtc::VoiceEngine::Create();
-    if (!mVoiceEngine) {
+  if (!mAudioInput) {
+    if (!SupportsDuplex()) {
       return;
     }
-  }
-
-  ptrVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
-  if (!ptrVoEBase) {
-    return;
-  }
-
-  // Always re-init the voice engine, since if we close the last use we
-  // DeInitEngine() and Terminate(), which shuts down Process() - but means
-  // we have to Init() again before using it.  Init() when already inited is
-  // just a no-op, so call always.
-  if (ptrVoEBase->Init() < 0) {
-    return;
-  }
-
-  if (!mAudioInput) {
-    if (SupportsDuplex()) {
-      // The platform_supports_full_duplex.
-      mAudioInput = new mozilla::AudioInputCubeb(mVoiceEngine);
-    } else {
-      mAudioInput = new mozilla::AudioInputWebRTC(mVoiceEngine);
-    }
+    mAudioInput = new mozilla::AudioInputCubeb();
   }
 
   int nDevices = 0;
   mAudioInput->GetNumOfRecordingDevices(nDevices);
   int i;
 #if defined(MOZ_WIDGET_ANDROID)
   i = 0; // Bug 1037025 - let the OS handle defaulting for now on android/b2g
 #else
@@ -339,36 +306,26 @@ MediaEngineWebRTC::EnumerateAudioDevices
     int error = mAudioInput->GetRecordingDeviceName(i, deviceName, uniqueId);
     if (error) {
       LOG((" AudioInput::GetRecordingDeviceName: Failed %d", error));
       continue;
     }
 
     if (uniqueId[0] == '\0') {
       // Mac and Linux don't set uniqueId!
-      MOZ_ASSERT(sizeof(deviceName) == sizeof(uniqueId)); // total paranoia
       strcpy(uniqueId, deviceName); // safe given assert and initialization/error-check
     }
 
     RefPtr<MediaEngineAudioSource> aSource;
     NS_ConvertUTF8toUTF16 uuid(uniqueId);
     if (mAudioSources.Get(uuid, getter_AddRefs(aSource))) {
       // We've already seen this device, just append.
       aASources->AppendElement(aSource.get());
     } else {
-      AudioInput* audioinput = mAudioInput;
-      if (SupportsDuplex()) {
-        // The platform_supports_full_duplex.
-
-        // For cubeb, it has state (the selected ID)
-        // XXX just use the uniqueID for cubeb and support it everywhere, and get rid of this
-        // XXX Small window where the device list/index could change!
-        audioinput = new mozilla::AudioInputCubeb(mVoiceEngine, i);
-      }
-      aSource = new MediaEngineWebRTCMicrophoneSource(mVoiceEngine, audioinput,
+      aSource = new MediaEngineWebRTCMicrophoneSource(new mozilla::AudioInputCubeb(i),
                                                       i, deviceName, uniqueId,
                                                       mDelayAgnostic, mExtendedFilter);
       mAudioSources.Put(uuid, aSource); // Hashtable takes ownership.
       aASources->AppendElement(aSource);
     }
   }
 }
 
@@ -396,20 +353,13 @@ MediaEngineWebRTC::Shutdown()
     MediaEngineAudioSource* source = iter.UserData();
     if (source) {
       source->Shutdown();
     }
   }
   mVideoSources.Clear();
   mAudioSources.Clear();
 
-  if (mVoiceEngine) {
-    mVoiceEngine->SetTraceCallback(nullptr);
-    webrtc::VoiceEngine::Delete(mVoiceEngine);
-  }
-
-  mVoiceEngine = nullptr;
-
   mozilla::camera::Shutdown();
   AudioInputCubeb::CleanupGlobalData();
 }
 
 }
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -136,17 +136,17 @@ protected:
   virtual ~MediaEngineWebRTCAudioCaptureSource() {}
   nsCString mUUID;
 };
 
 // Small subset of VoEHardware
 class AudioInput
 {
 public:
-  explicit AudioInput(webrtc::VoiceEngine* aVoiceEngine) : mVoiceEngine(aVoiceEngine) {};
+  AudioInput() = default;
   // Threadsafe because it's referenced from an MicrophoneSource, which can
   // had references to it on other threads.
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AudioInput)
 
   virtual int GetNumOfRecordingDevices(int& aDevices) = 0;
   virtual int GetRecordingDeviceName(int aIndex, char (&aStrNameUTF8)[128],
                                      char aStrGuidUTF8[128]) = 0;
   virtual int GetRecordingDeviceStatus(bool& aIsAvailable) = 0;
@@ -155,25 +155,23 @@ public:
   virtual void StartRecording(SourceMediaStream *aStream, AudioDataListener *aListener) = 0;
   virtual void StopRecording(SourceMediaStream *aStream) = 0;
   virtual int SetRecordingDevice(int aIndex) = 0;
   virtual void SetUserChannelCount(uint32_t aChannels) = 0;
 
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~AudioInput() {}
-
-  webrtc::VoiceEngine* mVoiceEngine;
 };
 
 class AudioInputCubeb final : public AudioInput
 {
 public:
-  explicit AudioInputCubeb(webrtc::VoiceEngine* aVoiceEngine, int aIndex = 0) :
-    AudioInput(aVoiceEngine), mSelectedDevice(aIndex), mInUseCount(0)
+  explicit AudioInputCubeb(int aIndex = 0) :
+    AudioInput(), mSelectedDevice(aIndex), mInUseCount(0)
   {
     if (!mDeviceIndexes) {
       mDeviceIndexes = new nsTArray<int>;
       mDeviceNames = new nsTArray<nsCString>;
       mDefaultDevice = -1;
     }
   }
 
@@ -309,24 +307,17 @@ public:
   {
 #ifdef MOZ_WIDGET_ANDROID
     // OpenSL ES does not support enumerating devices.
     MOZ_ASSERT(mDevices.count == 0);
 #else
     MOZ_ASSERT(mDevices.count > 0);
 #endif
 
-    if (mInUseCount == 0) {
-      ScopedCustomReleasePtr<webrtc::VoEExternalMedia> ptrVoEXMedia;
-      ptrVoEXMedia = webrtc::VoEExternalMedia::GetInterface(mVoiceEngine);
-      if (ptrVoEXMedia) {
-        ptrVoEXMedia->SetExternalRecordingStatus(true);
-      }
-      mAnyInUse = true;
-    }
+    mAnyInUse = true;
     mInUseCount++;
     // Always tell the stream we're using it for input
     aStream->OpenAudioInput(mSelectedDevice, aListener);
   }
 
   void StopRecording(SourceMediaStream *aStream)
   {
     aStream->CloseAudioInput();
@@ -364,87 +355,16 @@ private:
   static int mDefaultDevice; // -1 == not set
   static nsTArray<nsCString>* mDeviceNames;
   static cubeb_device_collection mDevices;
   static bool mAnyInUse;
   static StaticMutex sMutex;
   static uint32_t sUserChannelCount;
 };
 
-class AudioInputWebRTC final : public AudioInput
-{
-public:
-  explicit AudioInputWebRTC(webrtc::VoiceEngine* aVoiceEngine) : AudioInput(aVoiceEngine) {}
-
-  int GetNumOfRecordingDevices(int& aDevices)
-  {
-    ScopedCustomReleasePtr<webrtc::VoEBase> ptrVoEBase;
-    ptrVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
-    if (!ptrVoEBase)  {
-      return 1;
-    }
-    aDevices = ptrVoEBase->audio_device_module()->RecordingDevices();
-    return 0;
-  }
-
-  int GetRecordingDeviceName(int aIndex, char (&aStrNameUTF8)[128],
-                             char aStrGuidUTF8[128])
-  {
-    ScopedCustomReleasePtr<webrtc::VoEBase> ptrVoEBase;
-    ptrVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
-    if (!ptrVoEBase)  {
-      return 1;
-    }
-    return ptrVoEBase->audio_device_module()->RecordingDeviceName(aIndex,
-                                                                  aStrNameUTF8,
-                                                                  aStrGuidUTF8);
-  }
-
-  int GetRecordingDeviceStatus(bool& aIsAvailable)
-  {
-    ScopedCustomReleasePtr<webrtc::VoEBase> ptrVoEBase;
-    ptrVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
-    if (!ptrVoEBase)  {
-      return 1;
-    }
-    return ptrVoEBase->audio_device_module()->RecordingIsAvailable(&aIsAvailable);
-  }
-
-  void GetChannelCount(uint32_t& aChannels)
-  {
-    aChannels = 1; // default to mono
-  }
-
-  int GetMaxAvailableChannels(uint32_t& aChannels)
-  {
-    aChannels = 1;
-    return 0;
-  }
-
-  void SetUserChannelCount(uint32_t aChannels)
-  {}
-
-  void StartRecording(SourceMediaStream *aStream, AudioDataListener *aListener) {}
-  void StopRecording(SourceMediaStream *aStream) {}
-
-  int SetRecordingDevice(int aIndex)
-  {
-    ScopedCustomReleasePtr<webrtc::VoEBase> ptrVoEBase;
-    ptrVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
-    if (!ptrVoEBase)  {
-      return 1;
-    }
-    return ptrVoEBase->audio_device_module()->SetRecordingDevice(aIndex);
-  }
-
-protected:
-  // Protected destructor, to discourage deletion outside of Release():
-  ~AudioInputWebRTC() {}
-};
-
 class WebRTCAudioDataListener : public AudioDataListener
 {
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~WebRTCAudioDataListener() {}
 
 public:
   explicit WebRTCAudioDataListener(MediaEngineAudioSource* aAudioSource)
@@ -485,23 +405,21 @@ public:
     mAudioSource = nullptr;
   }
 
 private:
   Mutex mMutex;
   RefPtr<MediaEngineAudioSource> mAudioSource;
 };
 
-class MediaEngineWebRTCMicrophoneSource : public MediaEngineAudioSource,
-                                          public webrtc::VoEMediaProcess
+class MediaEngineWebRTCMicrophoneSource : public MediaEngineAudioSource
 {
   typedef MediaEngineAudioSource Super;
 public:
-  MediaEngineWebRTCMicrophoneSource(webrtc::VoiceEngine* aVoiceEnginePtr,
-                                    mozilla::AudioInput* aAudioInput,
+  MediaEngineWebRTCMicrophoneSource(mozilla::AudioInput* aAudioInput,
                                     int aIndex,
                                     const char* name,
                                     const char* uuid,
                                     bool aDelayAgnostic,
                                     bool aExtendedFilter);
 
   void GetName(nsAString& aName) const override;
   void GetUUID(nsACString& aUUID) const override;
@@ -545,114 +463,109 @@ public:
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   uint32_t GetBestFitnessDistance(
       const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
       const nsString& aDeviceId) const override;
 
-  // VoEMediaProcess.
-  virtual void Process(int channel, webrtc::ProcessingTypes type,
-                       int16_t audio10ms[], size_t length,
-                       int samplingFreq, bool isStereo) override;
-
   void Shutdown() override;
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
 protected:
   ~MediaEngineWebRTCMicrophoneSource() {}
 
 private:
   nsresult
   UpdateSingleSource(const AllocationHandle* aHandle,
                      const NormalizedConstraints& aNetConstraints,
                      const NormalizedConstraints& aNewConstraint,
                      const MediaEnginePrefs& aPrefs,
                      const nsString& aDeviceId,
                      const char** aOutBadConstraint) override;
 
+
+  void UpdateAECSettingsIfNeeded(bool aEnable, webrtc::EcModes aMode);
+  void UpdateAGCSettingsIfNeeded(bool aEnable, webrtc::AgcModes aMode);
+  void UpdateNSSettingsIfNeeded(bool aEnable, webrtc::NsModes aMode);
+
   void SetLastPrefs(const MediaEnginePrefs& aPrefs);
 
   // These allocate/configure and release the channel
   bool AllocChannel();
   void FreeChannel();
-  // These start/stop VoEBase and associated interfaces
-  bool InitEngine();
-  void DeInitEngine();
-
-  // This is true when all processing is disabled, we can skip
-  // packetization, resampling and other processing passes.
-  bool PassThrough() {
-    return mSkipProcessing;
-  }
   template<typename T>
   void InsertInGraph(const T* aBuffer,
                      size_t aFrames,
                      uint32_t aChannels);
 
   void PacketizeAndProcess(MediaStreamGraph* aGraph,
                            const AudioDataValue* aBuffer,
                            size_t aFrames,
                            TrackRate aRate,
                            uint32_t aChannels);
 
-  webrtc::VoiceEngine* mVoiceEngine;
+
+  // This is true when all processing is disabled, we can skip
+  // packetization, resampling and other processing passes.
+  bool PassThrough() {
+    return mSkipProcessing;
+  }
+  void SetPassThrough(bool aPassThrough) {
+    mSkipProcessing = aPassThrough;
+  }
+
   RefPtr<mozilla::AudioInput> mAudioInput;
   RefPtr<WebRTCAudioDataListener> mListener;
-  RefPtr<AudioOutputObserver> mAudioOutputObserver;
 
-  // Note: shared across all microphone sources - we don't want to Terminate()
-  // the VoEBase until there are no active captures
+  // Note: shared across all microphone sources
   static int sChannelsOpen;
-  static ScopedCustomReleasePtr<webrtc::VoEBase> mVoEBase;
-  static ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERender;
-  static ScopedCustomReleasePtr<webrtc::VoENetwork> mVoENetwork;
-  static ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mVoEProcessing;
 
+  const UniquePtr<webrtc::AudioProcessing> mAudioProcessing;
+  const RefPtr<AudioOutputObserver> mAudioOutputObserver;
 
   // accessed from the GraphDriver thread except for deletion
-  nsAutoPtr<AudioPacketizer<AudioDataValue, int16_t>> mPacketizer;
+  nsAutoPtr<AudioPacketizer<AudioDataValue, float>> mPacketizer;
   ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERenderListener;
 
   // mMonitor protects mSources[] and mPrinicpalIds[] access/changes, and
   // transitions of mState from kStarted to kStopped (which are combined with
   // EndTrack()). mSources[] and mPrincipalHandles[] are accessed from webrtc
   // threads.
   Monitor mMonitor;
   nsTArray<RefPtr<SourceMediaStream>> mSources;
   nsTArray<PrincipalHandle> mPrincipalHandles; // Maps to mSources.
 
   int mCapIndex;
-  int mChannel;
   bool mDelayAgnostic;
   bool mExtendedFilter;
   MOZ_INIT_OUTSIDE_CTOR TrackID mTrackID;
   bool mStarted;
 
   nsString mDeviceName;
   nsCString mDeviceUUID;
 
   int32_t mSampleFrequency;
   uint64_t mTotalFrames;
   uint64_t mLastLogFrames;
 
-  NullTransport *mNullTransport;
-
-  nsTArray<int16_t> mInputBuffer;
   // mSkipProcessing is true if none of the processing passes are enabled,
   // because of prefs or constraints. This allows simply copying the audio into
   // the MSG, skipping resampling and the whole webrtc.org code.
+  // This is read and written to only on the MSG thread.
   bool mSkipProcessing;
 
   // To only update microphone when needed, we keep track of previous settings.
   MediaEnginePrefs mLastPrefs;
 
-  AlignedShortBuffer mInputDownmixBuffer;
+  AlignedFloatBuffer mInputBuffer;
+  AlignedFloatBuffer mDeinterleavedBuffer;
+  AlignedAudioBuffer mInputDownmixBuffer;
 };
 
 class MediaEngineWebRTC : public MediaEngine
 {
   typedef MediaEngine Super;
 public:
   explicit MediaEngineWebRTC(MediaEnginePrefs& aPrefs);
 
@@ -671,17 +584,16 @@ public:
                              nsTArray<RefPtr<MediaEngineAudioSource>>*) override;
 private:
   ~MediaEngineWebRTC() {}
 
   nsCOMPtr<nsIThread> mThread;
 
   // gUM runnables can e.g. Enumerate from multiple threads
   Mutex mMutex;
-  webrtc::VoiceEngine* mVoiceEngine;
   RefPtr<mozilla::AudioInput> mAudioInput;
   bool mFullDuplex;
   bool mDelayAgnostic;
   bool mExtendedFilter;
   bool mHasTabVideoSource;
 
   // Store devices we've already seen in a hashtable for quick return.
   // Maps UUID to MediaEngineSource (one set for audio, one for video).
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -5,29 +5,28 @@
 #include "MediaEngineWebRTC.h"
 #include <stdio.h>
 #include <algorithm>
 #include "mozilla/Assertions.h"
 #include "MediaTrackConstraints.h"
 #include "mtransport/runnable_utils.h"
 #include "nsAutoPtr.h"
 #include "AudioConverter.h"
+#include "MediaStreamGraphImpl.h"
 
 // scoped_ptr.h uses FF
 #ifdef FF
 #undef FF
 #endif
 #include "webrtc/modules/audio_device/opensl/single_rw_fifo.h"
+#include "webrtc/voice_engine/voice_engine_defines.h"
+#include "webrtc/modules/audio_processing/include/audio_processing.h"
+#include "webrtc/common_audio/include/audio_util.h"
 
-#define CHANNELS 1
-#define ENCODING "L16"
-#define DEFAULT_PORT 5555
-
-#define SAMPLE_RATE(freq) ((freq)*2*8) // bps, 16-bit samples
-#define SAMPLE_LENGTH(freq) (((freq)*10)/1000)
+using namespace webrtc;
 
 // These are restrictions from the webrtc.org code
 #define MAX_CHANNELS 2
 #define MAX_SAMPLING_FREQ 48000 // Hz - multiple of 100
 
 #define MAX_AEC_FIFO_DEPTH 200 // ms - multiple of 10
 static_assert(!(MAX_AEC_FIFO_DEPTH % 10), "Invalid MAX_AEC_FIFO_DEPTH");
 
@@ -48,31 +47,27 @@ LogModule* AudioLogModule() {
 
 /**
  * Webrtc microphone source source.
  */
 NS_IMPL_ISUPPORTS0(MediaEngineWebRTCMicrophoneSource)
 NS_IMPL_ISUPPORTS0(MediaEngineWebRTCAudioCaptureSource)
 
 int MediaEngineWebRTCMicrophoneSource::sChannelsOpen = 0;
-ScopedCustomReleasePtr<webrtc::VoEBase> MediaEngineWebRTCMicrophoneSource::mVoEBase;
-ScopedCustomReleasePtr<webrtc::VoEExternalMedia> MediaEngineWebRTCMicrophoneSource::mVoERender;
-ScopedCustomReleasePtr<webrtc::VoENetwork> MediaEngineWebRTCMicrophoneSource::mVoENetwork;
-ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> MediaEngineWebRTCMicrophoneSource::mVoEProcessing;
 
 AudioOutputObserver::AudioOutputObserver()
   : mPlayoutFreq(0)
   , mPlayoutChannels(0)
   , mChunkSize(0)
   , mSaved(nullptr)
   , mSamplesSaved(0)
   , mDownmixBuffer(MAX_SAMPLING_FREQ * MAX_CHANNELS / 100)
 {
   // Buffers of 10ms chunks
-  mPlayoutFifo = new webrtc::SingleRwFifo(MAX_AEC_FIFO_DEPTH/10);
+  mPlayoutFifo = new SingleRwFifo(MAX_AEC_FIFO_DEPTH/10);
 }
 
 AudioOutputObserver::~AudioOutputObserver()
 {
   Clear();
   free(mSaved);
   mSaved = nullptr;
 }
@@ -138,38 +133,38 @@ AudioOutputObserver::InsertFarEnd(const 
     aOverran = false;
   }
   // Rechunk to 10ms.
   // The AnalyzeReverseStream() and WebRtcAec_BufferFarend() functions insist on 10ms
   // samples per call.  Annoying...
   while (aFrames) {
     if (!mSaved) {
       mSaved = (FarEndAudioChunk *) moz_xmalloc(sizeof(FarEndAudioChunk) +
-                                                (mChunkSize * channels - 1)*sizeof(int16_t));
+                                                (mChunkSize * channels - 1)*sizeof(AudioDataValue));
       mSaved->mSamples = mChunkSize;
       mSaved->mOverrun = aOverran;
       aOverran = false;
     }
     uint32_t to_copy = mChunkSize - mSamplesSaved;
     if (to_copy > aFrames) {
       to_copy = aFrames;
     }
 
-    int16_t* dest = &(mSaved->mData[mSamplesSaved * channels]);
+    AudioDataValue* dest = &(mSaved->mData[mSamplesSaved * channels]);
     if (aChannels > MAX_CHANNELS) {
       AudioConverter converter(AudioConfig(aChannels, 0), AudioConfig(channels, 0));
       converter.Process(mDownmixBuffer, aBuffer, to_copy);
       ConvertAudioSamples(mDownmixBuffer.Data(), dest, to_copy * channels);
     } else {
       ConvertAudioSamples(aBuffer, dest, to_copy * channels);
     }
 
 #ifdef LOG_FAREND_INSERTION
     if (fp) {
-      fwrite(&(mSaved->mData[mSamplesSaved * aChannels]), to_copy * aChannels, sizeof(int16_t), fp);
+      fwrite(&(mSaved->mData[mSamplesSaved * aChannels]), to_copy * aChannels, sizeof(AudioDataValue), fp);
     }
 #endif
     aFrames -= to_copy;
     mSamplesSaved += to_copy;
     aBuffer += to_copy * aChannels;
 
     if (mSamplesSaved >= mChunkSize) {
       int free_slots = mPlayoutFifo->capacity() - mPlayoutFifo->size();
@@ -182,41 +177,38 @@ AudioOutputObserver::InsertFarEnd(const 
         mSaved = nullptr;
         mSamplesSaved = 0;
       }
     }
   }
 }
 
 MediaEngineWebRTCMicrophoneSource::MediaEngineWebRTCMicrophoneSource(
-    webrtc::VoiceEngine* aVoiceEnginePtr,
     mozilla::AudioInput* aAudioInput,
     int aIndex,
     const char* name,
     const char* uuid,
     bool aDelayAgnostic,
     bool aExtendedFilter)
   : MediaEngineAudioSource(kReleased)
-  , mVoiceEngine(aVoiceEnginePtr)
   , mAudioInput(aAudioInput)
+  , mAudioProcessing(AudioProcessing::Create())
+  , mAudioOutputObserver(new AudioOutputObserver())
   , mMonitor("WebRTCMic.Monitor")
   , mCapIndex(aIndex)
-  , mChannel(-1)
   , mDelayAgnostic(aDelayAgnostic)
   , mExtendedFilter(aExtendedFilter)
   , mTrackID(TRACK_NONE)
   , mStarted(false)
-  , mSampleFrequency(MediaEngine::DEFAULT_SAMPLE_RATE)
+  , mSampleFrequency(MediaEngine::USE_GRAPH_RATE)
   , mTotalFrames(0)
   , mLastLogFrames(0)
-  , mNullTransport(nullptr)
   , mSkipProcessing(false)
   , mInputDownmixBuffer(MAX_SAMPLING_FREQ * MAX_CHANNELS / 100)
 {
-  MOZ_ASSERT(aVoiceEnginePtr);
   MOZ_ASSERT(aAudioInput);
   mDeviceName.Assign(NS_ConvertUTF8toUTF16(name));
   mDeviceUUID.Assign(uuid);
   mListener = new mozilla::WebRTCAudioDataListener(this);
   mSettings->mEchoCancellation.Construct(0);
   mSettings->mAutoGainControl.Construct(0);
   mSettings->mNoiseSuppression.Construct(0);
   mSettings->mChannelCount.Construct(0);
@@ -270,16 +262,150 @@ MediaEngineWebRTCMicrophoneSource::Resta
                               aOutBadConstraint);
 }
 
 bool operator == (const MediaEnginePrefs& a, const MediaEnginePrefs& b)
 {
   return !memcmp(&a, &b, sizeof(MediaEnginePrefs));
 };
 
+// This does an early return in case of error.
+#define HANDLE_APM_ERROR(fn)                                \
+do {                                                        \
+  int rv = fn;                                              \
+  if (rv != AudioProcessing::kNoError) {                    \
+    MOZ_ASSERT_UNREACHABLE("APM error in " #fn);            \
+    return;                                                 \
+  }                                                         \
+} while(0);
+
+void MediaEngineWebRTCMicrophoneSource::UpdateAECSettingsIfNeeded(bool aEnable, EcModes aMode)
+{
+  using webrtc::EcModes;
+
+  EchoCancellation::SuppressionLevel level;
+
+  switch(aMode) {
+    case EcModes::kEcUnchanged:
+      level = mAudioProcessing->echo_cancellation()->suppression_level();
+      break;
+    case EcModes::kEcConference:
+      level = EchoCancellation::kHighSuppression;
+      break;
+    case EcModes::kEcDefault:
+      level = EchoCancellation::kModerateSuppression;
+      break;
+    case EcModes::kEcAec:
+      level = EchoCancellation::kModerateSuppression;
+      break;
+    case EcModes::kEcAecm:
+      // No suppression level to set for the mobile echo canceller
+      break;
+    default:
+      MOZ_LOG(GetMediaManagerLog(), LogLevel::Error, ("Bad EcMode value"));
+      MOZ_ASSERT_UNREACHABLE("Bad pref set in all.js or in about:config"
+                             " for the echo cancelation mode.");
+      // fall back to something sensible in release
+      level = EchoCancellation::kModerateSuppression;
+      break;
+  }
+
+  // AECm and AEC are mutually exclusive.
+  if (aMode == EcModes::kEcAecm) {
+    HANDLE_APM_ERROR(mAudioProcessing->echo_cancellation()->Enable(false));
+    HANDLE_APM_ERROR(mAudioProcessing->echo_control_mobile()->Enable(aEnable));
+  } else {
+    HANDLE_APM_ERROR(mAudioProcessing->echo_control_mobile()->Enable(false));
+    HANDLE_APM_ERROR(mAudioProcessing->echo_cancellation()->Enable(aEnable));
+    HANDLE_APM_ERROR(mAudioProcessing->echo_cancellation()->set_suppression_level(level));
+  }
+}
+
+void
+MediaEngineWebRTCMicrophoneSource::UpdateAGCSettingsIfNeeded(bool aEnable, AgcModes aMode)
+{
+#if defined(WEBRTC_IOS) || defined(ATA) || defined(WEBRTC_ANDROID)
+  if (aMode == kAgcAdaptiveAnalog) {
+    MOZ_LOG(GetMediaManagerLog(),
+            LogLevel::Error,
+            ("Invalid AGC mode kAgcAdaptiveAnalog on mobile"));
+    MOZ_ASSERT_UNREACHABLE("Bad pref set in all.js or in about:config"
+                           " for the auto gain, on mobile.");
+    aMode = kAgcDefault;
+  }
+#endif
+  GainControl::Mode mode = kDefaultAgcMode;
+
+  switch (aMode) {
+    case AgcModes::kAgcDefault:
+      mode = kDefaultAgcMode;
+      break;
+    case AgcModes::kAgcUnchanged:
+      mode = mAudioProcessing->gain_control()->mode();
+      break;
+    case AgcModes::kAgcFixedDigital:
+      mode = GainControl::Mode::kFixedDigital;
+      break;
+    case AgcModes::kAgcAdaptiveAnalog:
+      mode = GainControl::Mode::kAdaptiveAnalog;
+      break;
+    case AgcModes::kAgcAdaptiveDigital:
+      mode = GainControl::Mode::kAdaptiveDigital;
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("Bad pref set in all.js or in about:config"
+                             " for the auto gain.");
+      // This is a good fallback, it works regardless of the platform.
+      mode = GainControl::Mode::kAdaptiveDigital;
+      break;
+  }
+
+  HANDLE_APM_ERROR(mAudioProcessing->gain_control()->set_mode(mode));
+  HANDLE_APM_ERROR(mAudioProcessing->gain_control()->Enable(aEnable));
+}
+
+void
+MediaEngineWebRTCMicrophoneSource::UpdateNSSettingsIfNeeded(bool aEnable, NsModes aMode)
+{
+  NoiseSuppression::Level nsLevel;
+
+  switch (aMode) {
+    case NsModes::kNsDefault:
+      nsLevel = kDefaultNsMode;
+      break;
+    case NsModes::kNsUnchanged:
+      nsLevel = mAudioProcessing->noise_suppression()->level();
+      break;
+    case NsModes::kNsConference:
+      nsLevel = NoiseSuppression::kHigh;
+      break;
+    case NsModes::kNsLowSuppression:
+      nsLevel = NoiseSuppression::kLow;
+      break;
+    case NsModes::kNsModerateSuppression:
+      nsLevel = NoiseSuppression::kModerate;
+      break;
+    case NsModes::kNsHighSuppression:
+      nsLevel = NoiseSuppression::kHigh;
+      break;
+    case NsModes::kNsVeryHighSuppression:
+      nsLevel = NoiseSuppression::kVeryHigh;
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("Bad pref set in all.js or in about:config"
+                             " for the noise suppression.");
+      // Pick something sensible as a faillback in release.
+      nsLevel = NoiseSuppression::kModerate;
+  }
+  HANDLE_APM_ERROR(mAudioProcessing->noise_suppression()->set_level(nsLevel));
+  HANDLE_APM_ERROR(mAudioProcessing->noise_suppression()->Enable(aEnable));
+}
+
+#undef HANDLE_APM_ERROR
+
 nsresult
 MediaEngineWebRTCMicrophoneSource::UpdateSingleSource(
     const AllocationHandle* aHandle,
     const NormalizedConstraints& aNetConstraints,
     const NormalizedConstraints& aNewConstraint, /* Ignored */
     const MediaEnginePrefs& aPrefs,
     const nsString& aDeviceId,
     const char** aOutBadConstraint)
@@ -313,22 +439,17 @@ MediaEngineWebRTCMicrophoneSource::Updat
       prefs.mAecOn ? prefs.mAec : -1,
       prefs.mAgcOn ? prefs.mAgc : -1,
       prefs.mNoiseOn ? prefs.mNoise : -1,
       prefs.mChannels));
 
   switch (mState) {
     case kReleased:
       MOZ_ASSERT(aHandle);
-      if (sChannelsOpen == 0) {
-        if (!InitEngine()) {
-          LOG(("Audio engine is not initalized"));
-          return NS_ERROR_FAILURE;
-        }
-      } else {
+      if (sChannelsOpen != 0) {
         // Until we fix (or wallpaper) support for multiple mic input
         // (Bug 1238038) fail allocation for a second device
         return NS_ERROR_FAILURE;
       }
       if (mAudioInput->SetRecordingDevice(mCapIndex)) {
          return NS_ERROR_FAILURE;
       }
       mAudioInput->SetUserChannelCount(prefs.mChannels);
@@ -350,29 +471,29 @@ MediaEngineWebRTCMicrophoneSource::Updat
 
     case kStarted:
       if (prefs == mLastPrefs) {
         return NS_OK;
       }
 
       if (prefs.mChannels != mLastPrefs.mChannels) {
         MOZ_ASSERT(mSources.Length() > 0);
+        // If the channel count changed, tell the MSG to open a new driver with
+        // the correct channel count.
         auto& source = mSources.LastElement();
         mAudioInput->SetUserChannelCount(prefs.mChannels);
         // Get validated number of channel
         uint32_t channelCount = 0;
         mAudioInput->GetChannelCount(channelCount);
         MOZ_ASSERT(channelCount > 0 && mLastPrefs.mChannels > 0);
-        // Check if new validated channels is the same as previous
-        if (static_cast<uint32_t>(mLastPrefs.mChannels) != channelCount &&
+        if (mLastPrefs.mChannels != prefs.mChannels &&
             !source->OpenNewAudioCallbackDriver(mListener)) {
+          MOZ_LOG(GetMediaManagerLog(), LogLevel::Error, ("Could not open a new AudioCallbackDriver for input"));
           return NS_ERROR_FAILURE;
         }
-        // Update settings
-        prefs.mChannels = channelCount;
       }
 
       if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) {
         MonitorAutoLock lock(mMonitor);
         if (mSources.IsEmpty()) {
           LOG(("Audio device %d reallocated", mCapIndex));
         } else {
           LOG(("Audio device %d allocated shared", mCapIndex));
@@ -381,74 +502,72 @@ MediaEngineWebRTCMicrophoneSource::Updat
       break;
 
     default:
       LOG(("Audio device %d in ignored state %d", mCapIndex, mState));
       break;
   }
 
   if (sChannelsOpen > 0) {
-    int error;
+    UpdateAGCSettingsIfNeeded(prefs.mAgcOn, static_cast<AgcModes>(prefs.mAgc));
+    UpdateNSSettingsIfNeeded(prefs.mNoiseOn, static_cast<NsModes>(prefs.mNoise));
+    UpdateAECSettingsIfNeeded(prefs.mAecOn, static_cast<EcModes>(prefs.mAec));
 
-    error = mVoEProcessing->SetEcStatus(prefs.mAecOn, (webrtc::EcModes)prefs.mAec);
-    if (error) {
-      LOG(("%s Error setting Echo Status: %d ",__FUNCTION__, error));
-      // Overhead of capturing all the time is very low (<0.1% of an audio only call)
-      if (prefs.mAecOn) {
-        error = mVoEProcessing->SetEcMetricsStatus(true);
-        if (error) {
-          LOG(("%s Error setting Echo Metrics: %d ",__FUNCTION__, error));
-        }
-      }
-    }
-    error = mVoEProcessing->SetAgcStatus(prefs.mAgcOn, (webrtc::AgcModes)prefs.mAgc);
-    if (error) {
-      LOG(("%s Error setting AGC Status: %d ",__FUNCTION__, error));
-    }
-    error = mVoEProcessing->SetNsStatus(prefs.mNoiseOn, (webrtc::NsModes)prefs.mNoise);
-    if (error) {
-      LOG(("%s Error setting NoiseSuppression Status: %d ",__FUNCTION__, error));
-    }
-  }
-
-  // we don't allow switching from non-fast-path to fast-path on the fly yet
-  if (mState != kStarted) {
-    mSkipProcessing = !(prefs.mAecOn || prefs.mAgcOn || prefs.mNoiseOn);
-    if (mSkipProcessing) {
-      mSampleFrequency = MediaEngine::USE_GRAPH_RATE;
-    } else {
-      // make sure we route a copy of the mixed audio output of this MSG to the
-      // AEC
-      if (!mAudioOutputObserver) {
-        mAudioOutputObserver = new AudioOutputObserver();
-      }
-    }
+    webrtc::Config config;
+    config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(mExtendedFilter));
+    config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(mDelayAgnostic));
+    mAudioProcessing->SetExtraOptions(config);
   }
   SetLastPrefs(prefs);
   return NS_OK;
 }
 
+#undef HANDLE_APM_ERROR
+
 void
-MediaEngineWebRTCMicrophoneSource::SetLastPrefs(
-    const MediaEnginePrefs& aPrefs)
+MediaEngineWebRTCMicrophoneSource::SetLastPrefs(const MediaEnginePrefs& aPrefs)
 {
   mLastPrefs = aPrefs;
 
   RefPtr<MediaEngineWebRTCMicrophoneSource> that = this;
 
   NS_DispatchToMainThread(media::NewRunnableFrom([that, aPrefs]() mutable {
     that->mSettings->mEchoCancellation.Value() = aPrefs.mAecOn;
     that->mSettings->mAutoGainControl.Value() = aPrefs.mAgcOn;
     that->mSettings->mNoiseSuppression.Value() = aPrefs.mNoiseOn;
     that->mSettings->mChannelCount.Value() = aPrefs.mChannels;
+
+    class Message : public ControlMessage {
+    public:
+      Message(MediaEngineWebRTCMicrophoneSource* aSource,
+              bool aPassThrough)
+        : ControlMessage(nullptr)
+        , mMicrophoneSource(aSource)
+        , mPassThrough(aPassThrough)
+        {}
+
+      void Run() override
+      {
+        mMicrophoneSource->SetPassThrough(mPassThrough);
+      }
+
+    protected:
+      RefPtr<MediaEngineWebRTCMicrophoneSource> mMicrophoneSource;
+      bool mPassThrough;
+    };
+
+    bool passThrough = !(aPrefs.mAecOn || aPrefs.mAgcOn || aPrefs.mNoiseOn);
+    if (!that->mSources.IsEmpty()) {
+      that->mSources[0]->GraphImpl()->AppendMessage(MakeUnique<Message>(that, passThrough));
+    }
+
     return NS_OK;
   }));
 }
 
-
 nsresult
 MediaEngineWebRTCMicrophoneSource::Deallocate(AllocationHandle* aHandle)
 {
   AssertIsOnOwningThread();
 
   Super::Deallocate(aHandle);
 
   if (!mRegisteredHandles.Length()) {
@@ -488,17 +607,17 @@ MediaEngineWebRTCMicrophoneSource::Start
     mPrincipalHandles.AppendElement(aPrincipalHandle);
     MOZ_ASSERT(mSources.Length() == mPrincipalHandles.Length());
   }
 
   AudioSegment* segment = new AudioSegment();
   if (mSampleFrequency == MediaEngine::USE_GRAPH_RATE) {
     mSampleFrequency = aStream->GraphRate();
   }
-  aStream->AddAudioTrack(aID, mSampleFrequency, 0, segment, SourceMediaStream::ADDTRACK_QUEUED);
+  aStream->AddAudioTrack(aID, aStream->GraphRate(), 0, segment, SourceMediaStream::ADDTRACK_QUEUED);
 
   // XXX Make this based on the pref.
   aStream->RegisterForAudioMixing();
   LOG(("Start audio for stream %p", aStream));
 
   if (!mListener) {
     mListener = new mozilla::WebRTCAudioDataListener(this);
   }
@@ -509,34 +628,20 @@ MediaEngineWebRTCMicrophoneSource::Start
     return NS_OK;
   }
   mState = kStarted;
   mTrackID = aID;
 
   // Make sure logger starts before capture
   AsyncLatencyLogger::Get(true);
 
-  if (mAudioOutputObserver) {
-    mAudioOutputObserver->Clear();
-  }
-
-  if (mVoEBase->StartReceive(mChannel)) {
-    return NS_ERROR_FAILURE;
-  }
+  mAudioOutputObserver->Clear();
 
-  // Must be *before* StartSend() so it will notice we selected external input (full_duplex)
   mAudioInput->StartRecording(aStream, mListener);
 
-  if (mVoEBase->StartSend(mChannel)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Attach external media processor, so this::Process will be called.
-  mVoERender->RegisterExternalMediaProcessing(mChannel, webrtc::kRecordingPerChannel, *this);
-
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCMicrophoneSource::Stop(SourceMediaStream *aSource, TrackID aID)
 {
   AssertIsOnOwningThread();
   {
@@ -555,38 +660,27 @@ MediaEngineWebRTCMicrophoneSource::Stop(
 
     if (!mSources.IsEmpty()) {
       mAudioInput->StopRecording(aSource);
       return NS_OK;
     }
     if (mState != kStarted) {
       return NS_ERROR_FAILURE;
     }
-    if (!mVoEBase) {
-      return NS_ERROR_FAILURE;
-    }
 
     mState = kStopped;
   }
   if (mListener) {
     // breaks a cycle, since the WebRTCAudioDataListener has a RefPtr to us
     mListener->Shutdown();
     mListener = nullptr;
   }
 
   mAudioInput->StopRecording(aSource);
 
-  mVoERender->DeRegisterExternalMediaProcessing(mChannel, webrtc::kRecordingPerChannel);
-
-  if (mVoEBase->StopSend(mChannel)) {
-    return NS_ERROR_FAILURE;
-  }
-  if (mVoEBase->StopReceive(mChannel)) {
-    return NS_ERROR_FAILURE;
-  }
   return NS_OK;
 }
 
 void
 MediaEngineWebRTCMicrophoneSource::NotifyPull(MediaStreamGraph *aGraph,
                                               SourceMediaStream *aSource,
                                               TrackID aID,
                                               StreamTime aDesiredTime,
@@ -598,58 +692,229 @@ MediaEngineWebRTCMicrophoneSource::Notif
 
 void
 MediaEngineWebRTCMicrophoneSource::NotifyOutputData(MediaStreamGraph* aGraph,
                                                     AudioDataValue* aBuffer,
                                                     size_t aFrames,
                                                     TrackRate aRate,
                                                     uint32_t aChannels)
 {
-  if (mAudioOutputObserver) {
+  if (!PassThrough()) {
     mAudioOutputObserver->InsertFarEnd(aBuffer, aFrames, false,
-                                  aRate, aChannels);
+                                       aRate, aChannels);
   }
 }
 
+// Only called if we're not in passthrough mode
 void
 MediaEngineWebRTCMicrophoneSource::PacketizeAndProcess(MediaStreamGraph* aGraph,
                                                        const AudioDataValue* aBuffer,
                                                        size_t aFrames,
                                                        TrackRate aRate,
                                                        uint32_t aChannels)
 {
-  // This will call Process() with data coming out of the AEC/NS/AGC/etc chain
+  MOZ_ASSERT(!PassThrough(), "This should be bypassed when in PassThrough mode.");
+  size_t offset = 0;
+
   if (!mPacketizer ||
       mPacketizer->PacketSize() != aRate/100u ||
       mPacketizer->Channels() != aChannels) {
     // It's ok to drop the audio still in the packetizer here.
     mPacketizer =
-      new AudioPacketizer<AudioDataValue, int16_t>(aRate/100, aChannels);
+      new AudioPacketizer<AudioDataValue, float>(aRate/100, aChannels);
+  }
+
+  // On initial capture, throw away all far-end data except the most recent sample
+  // since it's already irrelevant and we want to keep avoid confusing the AEC far-end
+  // input code with "old" audio.
+  if (!mStarted) {
+    mStarted  = true;
+    while (mAudioOutputObserver->Size() > 1) {
+      free(mAudioOutputObserver->Pop()); // only call if size() > 0
+    }
   }
 
+  // Feed the far-end audio data (speakers) to the feedback input of the AEC.
+  while (mAudioOutputObserver->Size() > 0) {
+    // Bug 1414837: This will call `free()`, and we should remove it.
+    // Pop gives ownership.
+    nsAutoPtr<FarEndAudioChunk> buffer(mAudioOutputObserver->Pop()); // only call if size() > 0
+    if (!buffer) {
+      continue;
+    }
+    AudioDataValue* packetDataPointer = buffer->mData;
+    AutoTArray<AudioDataValue*, MAX_CHANNELS> deinterleavedPacketDataChannelPointers;
+    AudioDataValue* interleavedFarend = nullptr;
+    uint32_t channelCountFarend = 0;
+    uint32_t framesPerPacketFarend = 0;
+
+    // Downmix from aChannels to MAX_CHANNELS if needed
+    if (mAudioOutputObserver->PlayoutChannels() > MAX_CHANNELS) {
+      AudioConverter converter(AudioConfig(aChannels, 0, AudioConfig::FORMAT_DEFAULT),
+                               AudioConfig(MAX_CHANNELS, 0, AudioConfig::FORMAT_DEFAULT));
+      framesPerPacketFarend =
+        buffer->mSamples;
+      framesPerPacketFarend =
+        converter.Process(mInputDownmixBuffer,
+                          packetDataPointer,
+                          framesPerPacketFarend);
+      interleavedFarend = mInputDownmixBuffer.Data();
+      channelCountFarend = MAX_CHANNELS;
+      deinterleavedPacketDataChannelPointers.SetLength(MAX_CHANNELS);
+    } else {
+      uint32_t outputChannels = mAudioOutputObserver->PlayoutChannels();
+      interleavedFarend = packetDataPointer;
+      channelCountFarend = outputChannels;
+      framesPerPacketFarend = buffer->mSamples;
+      deinterleavedPacketDataChannelPointers.SetLength(outputChannels);
+    }
+
+    MOZ_ASSERT(interleavedFarend &&
+               (channelCountFarend == 1 || channelCountFarend == 2) &&
+               framesPerPacketFarend);
+
+    offset = 0;
+    for (size_t i = 0; i < deinterleavedPacketDataChannelPointers.Length(); ++i) {
+      deinterleavedPacketDataChannelPointers[i] = packetDataPointer + offset;
+      offset += framesPerPacketFarend;
+    }
+
+    // deinterleave back into the FarEndAudioChunk buffer to save an alloc.
+    // There is enough room because either there is the same number of
+    // channels/frames or we've just downmixed.
+    Deinterleave(interleavedFarend,
+                 framesPerPacketFarend,
+                 channelCountFarend,
+                 deinterleavedPacketDataChannelPointers.Elements());
+
+    // Having the same config for input and output means we potentially save
+    // some CPU. We won't need the output here, the API forces us to set a
+    // valid pointer with enough space.
+    StreamConfig inputConfig(mAudioOutputObserver->PlayoutFrequency(),
+                             channelCountFarend,
+                             false /* we don't use typing detection*/);
+    StreamConfig outputConfig = inputConfig;
+
+    // Prepare a channel pointers array, with enough storage for the
+    // frames.
+    //
+    // If this is a platform that uses s16 for audio input and output,
+    // convert to floats, the APM API we use only accepts floats.
+
+    float* inputData = nullptr;
+#ifdef MOZ_SAMPLE_TYPE_S16
+    // Convert to floats, use mInputBuffer for this.
+    size_t sampleCount = framesPerPacketFarend * channelCountFarend;
+    if (mInputBuffer.Length() < sampleCount) {
+      mInputBuffer.SetLength(sampleCount);
+    }
+    ConvertAudioSamples(buffer->mData, mInputBuffer.Data(), sampleCount);
+    inputData = mInputBuffer.Data();
+#else // MOZ_SAMPLE_TYPE_F32
+    inputData = buffer->mData;
+#endif
+
+    AutoTArray<float*, MAX_CHANNELS> channelsPointers;
+    channelsPointers.SetLength(channelCountFarend);
+    offset = 0;
+    for (size_t i = 0; i < channelsPointers.Length(); ++i) {
+      channelsPointers[i]  = inputData + offset;
+      offset += framesPerPacketFarend;
+    }
+
+    // Passing the same pointers here saves a copy inside this function.
+    int err =
+      mAudioProcessing->ProcessReverseStream(channelsPointers.Elements(),
+                                             inputConfig,
+                                             outputConfig,
+                                             channelsPointers.Elements());
+
+    if (err) {
+      MOZ_LOG(GetMediaManagerLog(), LogLevel::Error,
+          ("error in audio ProcessReverseStream(): %d", err));
+      return;
+    }
+  }
+
+  // Packetize our input data into 10ms chunks, deinterleave into planar channel
+  // buffers, process, and append to the right MediaStreamTrack.
   mPacketizer->Input(aBuffer, static_cast<uint32_t>(aFrames));
 
   while (mPacketizer->PacketsAvailable()) {
     uint32_t samplesPerPacket = mPacketizer->PacketSize() *
       mPacketizer->Channels();
     if (mInputBuffer.Length() < samplesPerPacket) {
       mInputBuffer.SetLength(samplesPerPacket);
+      mDeinterleavedBuffer.SetLength(samplesPerPacket);
     }
-    int16_t* packet = mInputBuffer.Elements();
+    float* packet = mInputBuffer.Data();
     mPacketizer->Output(packet);
 
-    if (aChannels > MAX_CHANNELS) {
-      AudioConverter converter(AudioConfig(aChannels, 0, AudioConfig::FORMAT_S16),
-                               AudioConfig(MAX_CHANNELS, 0, AudioConfig::FORMAT_S16));
-      converter.Process(mInputDownmixBuffer, packet, mPacketizer->PacketSize());
-      mVoERender->ExternalRecordingInsertData(mInputDownmixBuffer.Data(),
-                                              mPacketizer->PacketSize() * MAX_CHANNELS,
-                                              aRate, 0);
-    } else {
-      mVoERender->ExternalRecordingInsertData(packet, samplesPerPacket, aRate, 0);
+    // Deinterleave the input data
+    // Prepare an array pointing to deinterleaved channels.
+    AutoTArray<float*, 8> deinterleavedPacketizedInputDataChannelPointers;
+    deinterleavedPacketizedInputDataChannelPointers.SetLength(aChannels);
+    offset = 0;
+    for (size_t i = 0; i < deinterleavedPacketizedInputDataChannelPointers.Length(); ++i) {
+      deinterleavedPacketizedInputDataChannelPointers[i] = mDeinterleavedBuffer.Data() + offset;
+      offset += aFrames;
+    }
+
+    // Deinterleave to mInputBuffer, pointed to by inputBufferChannelPointers.
+    Deinterleave(packet, mPacketizer->PacketSize(), aChannels,
+        deinterleavedPacketizedInputDataChannelPointers.Elements());
+
+    StreamConfig inputConfig(aRate,
+                             aChannels,
+                             false /* we don't use typing detection*/);
+    StreamConfig outputConfig = inputConfig;
+
+    // Bug 1404965: Get the right delay here, it saves some work down the line.
+    mAudioProcessing->set_stream_delay_ms(0);
+
+    // Bug 1414837: find a way to not allocate here.
+    RefPtr<SharedBuffer> buffer =
+      SharedBuffer::Create(mPacketizer->PacketSize() * aChannels * sizeof(float));
+    AudioSegment segment;
+
+    // Prepare channel pointers to the SharedBuffer created above.
+    AutoTArray<float*, 8> processedOutputChannelPointers;
+    AutoTArray<const float*, 8> processedOutputChannelPointersConst;
+    processedOutputChannelPointers.SetLength(aChannels);
+    processedOutputChannelPointersConst.SetLength(aChannels);
+
+    offset = 0;
+    for (size_t i = 0; i < processedOutputChannelPointers.Length(); ++i) {
+      processedOutputChannelPointers[i] = static_cast<float*>(buffer->Data()) + offset;
+      processedOutputChannelPointersConst[i] = static_cast<float*>(buffer->Data()) + offset;
+      offset += aFrames;
+    }
+
+    mAudioProcessing->ProcessStream(deinterleavedPacketizedInputDataChannelPointers.Elements(),
+                                    inputConfig,
+                                    outputConfig,
+                                    processedOutputChannelPointers.Elements());
+    MonitorAutoLock lock(mMonitor);
+    if (mState != kStarted)
+      return;
+
+    for (size_t i = 0; i < mSources.Length(); ++i) {
+      if (!mSources[i]) { // why ?!
+        continue;
+      }
+
+      // We already have planar audio data of the right format. Insert into the
+      // MSG.
+      MOZ_ASSERT(processedOutputChannelPointers.Length() == aChannels);
+      RefPtr<SharedBuffer> other = buffer;
+      segment.AppendFrames(other.forget(),
+                           processedOutputChannelPointersConst,
+                           mPacketizer->PacketSize(),
+                           mPrincipalHandles[i]);
+      mSources[i]->AppendToTrack(mTrackID, &segment);
     }
   }
 }
 
 template<typename T>
 void
 MediaEngineWebRTCMicrophoneSource::InsertInGraph(const T* aBuffer,
                                                  size_t aFrames,
@@ -666,33 +931,33 @@ MediaEngineWebRTCMicrophoneSource::Inser
       MOZ_LOG(AudioLogModule(), LogLevel::Debug,
               ("%p: Inserting %zu samples into graph, total frames = %" PRIu64,
                (void*)this, aFrames, mTotalFrames));
       mLastLogFrames = mTotalFrames;
     }
   }
 
   size_t len = mSources.Length();
-  for (size_t i = 0; i < len; i++) {
+  for (size_t i = 0; i < len; ++i) {
     if (!mSources[i]) {
       continue;
     }
 
     TimeStamp insertTime;
     // Make sure we include the stream and the track.
     // The 0:1 is a flag to note when we've done the final insert for a given input block.
     LogTime(AsyncLatencyLogger::AudioTrackInsertion,
             LATENCY_STREAM_ID(mSources[i].get(), mTrackID),
             (i+1 < len) ? 0 : 1, insertTime);
 
     // Bug 971528 - Support stereo capture in gUM
     MOZ_ASSERT(aChannels >= 1 && aChannels <= 8,
                "Support up to 8 channels");
 
-    nsAutoPtr<AudioSegment> segment(new AudioSegment());
+    AudioSegment segment;
     RefPtr<SharedBuffer> buffer =
       SharedBuffer::Create(aFrames * aChannels * sizeof(T));
     AutoTArray<const T*, 8> channels;
     if (aChannels == 1) {
       PodCopy(static_cast<T*>(buffer->Data()), aBuffer, aFrames);
       channels.AppendElement(static_cast<T*>(buffer->Data()));
     } else {
       channels.SetLength(aChannels);
@@ -708,21 +973,21 @@ MediaEngineWebRTCMicrophoneSource::Inser
 
       DeinterleaveAndConvertBuffer(aBuffer,
                                    aFrames,
                                    aChannels,
                                    write_channels.Elements());
     }
 
     MOZ_ASSERT(aChannels == channels.Length());
-    segment->AppendFrames(buffer.forget(), channels, aFrames,
+    segment.AppendFrames(buffer.forget(), channels, aFrames,
                          mPrincipalHandles[i]);
-    segment->GetStartTime(insertTime);
+    segment.GetStartTime(insertTime);
 
-    mSources[i]->AppendToTrack(mTrackID, segment);
+    mSources[i]->AppendToTrack(mTrackID, &segment);
   }
 }
 
 // Called back on GraphDriver thread!
 // Note this can be called back after ::Shutdown()
 void
 MediaEngineWebRTCMicrophoneSource::NotifyInputData(MediaStreamGraph* aGraph,
                                                    const AudioDataValue* aBuffer,
@@ -736,174 +1001,64 @@ MediaEngineWebRTCMicrophoneSource::Notif
     InsertInGraph<AudioDataValue>(aBuffer, aFrames, aChannels);
   } else {
     PacketizeAndProcess(aGraph, aBuffer, aFrames, aRate, aChannels);
   }
 }
 
 #define ResetProcessingIfNeeded(_processing)                        \
 do {                                                                \
-  webrtc::_processing##Modes mode;                                  \
-  int rv = mVoEProcessing->Get##_processing##Status(enabled, mode); \
-  if (rv) {                                                         \
-    NS_WARNING("Could not get the status of the "                   \
-     #_processing " on device change.");                            \
-    return;                                                         \
-  }                                                                 \
+  bool enabled = mAudioProcessing->_processing()->is_enabled();     \
                                                                     \
   if (enabled) {                                                    \
-    rv = mVoEProcessing->Set##_processing##Status(!enabled);        \
+    int rv = mAudioProcessing->_processing()->Enable(!enabled);     \
+    if (rv) {                                                       \
+      NS_WARNING("Could not reset the status of the "               \
+      #_processing " on device change.");                           \
+      return;                                                       \
+    }                                                               \
+    rv = mAudioProcessing->_processing()->Enable(enabled);          \
     if (rv) {                                                       \
       NS_WARNING("Could not reset the status of the "               \
       #_processing " on device change.");                           \
       return;                                                       \
     }                                                               \
                                                                     \
-    rv = mVoEProcessing->Set##_processing##Status(enabled);         \
-    if (rv) {                                                       \
-      NS_WARNING("Could not reset the status of the "               \
-      #_processing " on device change.");                           \
-      return;                                                       \
-    }                                                               \
   }                                                                 \
 }  while(0)
 
 void
 MediaEngineWebRTCMicrophoneSource::DeviceChanged() {
   // Reset some processing
-  bool enabled;
-  ResetProcessingIfNeeded(Agc);
-  ResetProcessingIfNeeded(Ec);
-  ResetProcessingIfNeeded(Ns);
+  ResetProcessingIfNeeded(gain_control);
+  ResetProcessingIfNeeded(echo_cancellation);
+  ResetProcessingIfNeeded(noise_suppression);
 }
 
-bool
-MediaEngineWebRTCMicrophoneSource::InitEngine()
-{
-  MOZ_ASSERT(!mVoEBase);
-  mVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
-
-  mVoEBase->Init();
-  webrtc::Config config;
-  config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(mExtendedFilter));
-  config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(mDelayAgnostic));
-  mVoEBase->audio_processing()->SetExtraOptions(config);
-
-  mVoERender = webrtc::VoEExternalMedia::GetInterface(mVoiceEngine);
-  if (mVoERender) {
-    mVoENetwork = webrtc::VoENetwork::GetInterface(mVoiceEngine);
-    if (mVoENetwork) {
-      mVoEProcessing = webrtc::VoEAudioProcessing::GetInterface(mVoiceEngine);
-      if (mVoEProcessing) {
-        mNullTransport = new NullTransport();
-        return true;
-      }
-    }
-  }
-  DeInitEngine();
-  return false;
-}
-
-// This shuts down the engine when no channel is open
-void
-MediaEngineWebRTCMicrophoneSource::DeInitEngine()
-{
-  if (mVoEBase) {
-    mVoEBase->Terminate();
-    delete mNullTransport;
-    mNullTransport = nullptr;
-
-    mVoEProcessing = nullptr;
-    mVoENetwork = nullptr;
-    mVoERender = nullptr;
-    mVoEBase = nullptr;
-  }
-}
-
-// This shuts down the engine when no channel is open.
 // mState records if a channel is allocated (slightly redundantly to mChannel)
 void
 MediaEngineWebRTCMicrophoneSource::FreeChannel()
 {
   if (mState != kReleased) {
-    if (mChannel != -1) {
-      MOZ_ASSERT(mVoENetwork && mVoEBase);
-      if (mVoENetwork) {
-        mVoENetwork->DeRegisterExternalTransport(mChannel);
-      }
-      if (mVoEBase) {
-        mVoEBase->DeleteChannel(mChannel);
-      }
-      mChannel = -1;
-    }
     mState = kReleased;
 
     MOZ_ASSERT(sChannelsOpen > 0);
-    if (--sChannelsOpen == 0) {
-      DeInitEngine();
-    }
+    --sChannelsOpen;
   }
 }
 
 bool
 MediaEngineWebRTCMicrophoneSource::AllocChannel()
 {
-  MOZ_ASSERT(mVoEBase);
-
-  mChannel = mVoEBase->CreateChannel();
-  if (mChannel >= 0) {
-    if (!mVoENetwork->RegisterExternalTransport(mChannel, *mNullTransport)) {
-      mSampleFrequency = MediaEngine::DEFAULT_SAMPLE_RATE;
-      LOG(("%s: sampling rate %u", __FUNCTION__, mSampleFrequency));
-
-      // Check for availability.
-      if (!mAudioInput->SetRecordingDevice(mCapIndex)) {
-        // Because of the permission mechanism of B2G, we need to skip the status
-        // check here.
-        bool avail = false;
-        mAudioInput->GetRecordingDeviceStatus(avail);
-        if (!avail) {
-          if (sChannelsOpen == 0) {
-            DeInitEngine();
-          }
-          return false;
-        }
+  mSampleFrequency = MediaEngine::USE_GRAPH_RATE;
+  LOG(("%s: sampling rate %u", __FUNCTION__, mSampleFrequency));
 
-        // Set "codec" to PCM, 32kHz on device's channels
-        ScopedCustomReleasePtr<webrtc::VoECodec> ptrVoECodec(webrtc::VoECodec::GetInterface(mVoiceEngine));
-        if (ptrVoECodec) {
-          webrtc::CodecInst codec;
-          strcpy(codec.plname, ENCODING);
-          codec.channels = CHANNELS;
-          uint32_t maxChannels = 0;
-          if (mAudioInput->GetMaxAvailableChannels(maxChannels) == 0) {
-            MOZ_ASSERT(maxChannels);
-            codec.channels = std::min<uint32_t>(maxChannels, MAX_CHANNELS);
-          }
-          MOZ_ASSERT(mSampleFrequency == 16000 || mSampleFrequency == 32000);
-          codec.rate = SAMPLE_RATE(mSampleFrequency);
-          codec.plfreq = mSampleFrequency;
-          codec.pacsize = SAMPLE_LENGTH(mSampleFrequency);
-          codec.pltype = 0; // Default payload type
-
-          if (!ptrVoECodec->SetSendCodec(mChannel, codec)) {
-            mState = kAllocated;
-            sChannelsOpen++;
-            return true;
-          }
-        }
-      }
-    }
-  }
-  mVoEBase->DeleteChannel(mChannel);
-  mChannel = -1;
-  if (sChannelsOpen == 0) {
-    DeInitEngine();
-  }
-  return false;
+  mState = kAllocated;
+  sChannelsOpen++;
+  return true;
 }
 
 void
 MediaEngineWebRTCMicrophoneSource::Shutdown()
 {
   Super::Shutdown();
   if (mListener) {
     // breaks a cycle, since the WebRTCAudioDataListener has a RefPtr to us
@@ -931,56 +1086,16 @@ MediaEngineWebRTCMicrophoneSource::Shutd
   }
 
   while (mRegisteredHandles.Length()) {
     MOZ_ASSERT(mState == kAllocated || mState == kStopped);
     // on last Deallocate(), FreeChannel()s and DeInit()s if all channels are released
     Deallocate(mRegisteredHandles[0].get());
   }
   MOZ_ASSERT(mState == kReleased);
-
-  mAudioInput = nullptr;
-}
-
-typedef int16_t sample;
-
-void
-MediaEngineWebRTCMicrophoneSource::Process(int channel,
-                                           webrtc::ProcessingTypes type,
-                                           sample *audio10ms, size_t length,
-                                           int samplingFreq, bool isStereo)
-{
-  MOZ_ASSERT(!PassThrough(), "This should be bypassed when in PassThrough mode.");
-  // On initial capture, throw away all far-end data except the most recent sample
-  // since it's already irrelevant and we want to keep avoid confusing the AEC far-end
-  // input code with "old" audio.
-  if (!mStarted) {
-    mStarted  = true;
-    while (mAudioOutputObserver->Size() > 1) {
-      free(mAudioOutputObserver->Pop()); // only call if size() > 0
-    }
-  }
-
-  while (mAudioOutputObserver->Size() > 0) {
-    FarEndAudioChunk *buffer = mAudioOutputObserver->Pop(); // only call if size() > 0
-    if (buffer) {
-      int length = buffer->mSamples;
-      int res = mVoERender->ExternalPlayoutData(buffer->mData,
-                                                mAudioOutputObserver->PlayoutFrequency(),
-                                                mAudioOutputObserver->PlayoutChannels(),
-                                                length);
-      free(buffer);
-      if (res == -1) {
-        return;
-      }
-    }
-  }
-
-  uint32_t channels = isStereo ? 2 : 1;
-  InsertInGraph<int16_t>(audio10ms, length, channels);
 }
 
 void
 MediaEngineWebRTCAudioCaptureSource::GetName(nsAString &aName) const
 {
   aName.AssignLiteral("AudioCapture");
 }
 
--- a/dom/media/webrtc/moz.build
+++ b/dom/media/webrtc/moz.build
@@ -34,21 +34,22 @@ if CONFIG['MOZ_WEBRTC']:
         'RTCCertificate.cpp',
         'RTCIdentityProviderRegistrar.cpp',
     ]
     # MediaEngineWebRTC.cpp needs to be built separately.
     SOURCES += [
         'MediaEngineWebRTC.cpp',
     ]
     LOCAL_INCLUDES += [
+        '..',
         '/dom/base',
         '/media/libyuv/libyuv/include',
         '/media/webrtc/signaling/src/common',
         '/media/webrtc/signaling/src/common/browser_logging',
-        '/media/webrtc/trunk',
+        '/media/webrtc/trunk'
     ]
 
 XPIDL_SOURCES += [
     'nsITabSource.idl'
 ]
 
 UNIFIED_SOURCES += [
     'MediaEngineDefault.cpp',
--- a/dom/performance/PerformanceMainThread.cpp
+++ b/dom/performance/PerformanceMainThread.cpp
@@ -136,16 +136,27 @@ PerformanceMainThread::AddEntry(nsIHttpC
 
     // According to the spec, "The name attribute must return the resolved URL
     // of the requested resource. This attribute must not change even if the
     // fetch redirected to a different URL."
     channel->GetOriginalURI(getter_AddRefs(originalURI));
     originalURI->GetSpec(name);
     NS_ConvertUTF8toUTF16 entryName(name);
 
+    bool reportTiming = true;
+    timedChannel->GetReportResourceTiming(&reportTiming);
+
+    if (!reportTiming) {
+#ifdef DEBUG_jwatt
+      NS_WARNING(
+        nsPrintfCString("Not reporting CORS resource: %s", name.get()).get());
+#endif
+      return;
+    }
+
     // The nsITimedChannel argument will be used to gather all the timings.
     // The nsIHttpChannel argument will be used to check if any cross-origin
     // redirects occurred.
     // The last argument is the "zero time" (offset). Since we don't want
     // any offset for the resource timing, this will be set to "0" - the
     // resource timing returns a relative timing (no offset).
     RefPtr<PerformanceTiming> performanceTiming =
         new PerformanceTiming(this, timedChannel, channel,
--- a/dom/performance/PerformanceTiming.cpp
+++ b/dom/performance/PerformanceTiming.cpp
@@ -47,16 +47,33 @@ PerformanceTiming::PerformanceTiming(Per
   // in subframes, and resources linked from a document.
   if (aHttpChannel) {
     mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel);
     bool redirectsPassCheck = false;
     aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck);
     mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck;
   }
 
+  mSecureConnection = false;
+  nsCOMPtr<nsIURI> uri;
+  if (aHttpChannel) {
+    aHttpChannel->GetURI(getter_AddRefs(uri));
+  } else {
+    nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+    if (httpChannel) {
+      httpChannel->GetURI(getter_AddRefs(uri));
+    }
+  }
+
+  if (uri) {
+    nsresult rv = uri->SchemeIs("https", &mSecureConnection);
+    if (NS_FAILED(rv)) {
+      mSecureConnection = false;
+    }
+  }
   InitializeTimingInfo(aChannel);
 
   // Non-null aHttpChannel implies that this PerformanceTiming object is being
   // used for subresources, which is irrelevant to this probe.
   if (!aHttpChannel &&
       nsContentUtils::IsPerformanceTimingEnabled() &&
       IsTopLevelContentDocument()) {
     Telemetry::Accumulate(Telemetry::TIME_TO_RESPONSE_START_MS,
@@ -113,17 +130,18 @@ PerformanceTiming::InitializeTimingInfo(
       if (!mDomainLookupEnd.IsNull() && mDomainLookupEnd < *clampTime) {
         mDomainLookupEnd = *clampTime;
       }
 
       if (!mConnectStart.IsNull() && mConnectStart < *clampTime) {
         mConnectStart = *clampTime;
       }
 
-      if (!mSecureConnectionStart.IsNull() && mSecureConnectionStart < *clampTime) {
+      if (mSecureConnection && !mSecureConnectionStart.IsNull() &&
+          mSecureConnectionStart < *clampTime) {
         mSecureConnectionStart = *clampTime;
       }
 
       if (!mConnectEnd.IsNull() && mConnectEnd < *clampTime) {
         mConnectEnd = *clampTime;
       }
     }
   }
@@ -364,18 +382,21 @@ PerformanceTiming::ConnectStart()
 
 DOMHighResTimeStamp
 PerformanceTiming::SecureConnectionStartHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
       nsContentUtils::ShouldResistFingerprinting()) {
     return mZeroTime;
   }
-  return mSecureConnectionStart.IsNull() ? mZeroTime
-                                         : TimeStampToDOMHighRes(mSecureConnectionStart);
+  return !mSecureConnection
+    ? 0 // We use 0 here, because mZeroTime is sometimes set to the navigation
+        // start time.
+    : (mSecureConnectionStart.IsNull() ? mZeroTime
+                                       : TimeStampToDOMHighRes(mSecureConnectionStart));
 }
 
 DOMTimeMilliSec
 PerformanceTiming::SecureConnectionStart()
 {
   return static_cast<int64_t>(SecureConnectionStartHighRes());
 }
 
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -300,14 +300,16 @@ private:
   bool mTimingAllowed;
   bool mAllRedirectsSameOrigin;
   bool mInitialized;
 
   // If the resourceTiming object should have non-zero redirectStart and
   // redirectEnd attributes. It is false if there were no redirects, or if
   // any of the responses didn't pass the timing-allow-check
   bool mReportCrossOriginRedirect;
+
+  bool mSecureConnection;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PerformanceTiming_h
--- a/dom/performance/tests/test_performance_user_timing.js
+++ b/dom/performance/tests/test_performance_user_timing.js
@@ -261,15 +261,15 @@ var steps = [
             try {
                 if (n == "toJSON") {
                     ok(true, "Skipping toJSON entry in collision test");
                     continue;
                 }
                 performance.measure("test", n);
                 ok(true, "Measure created from reserved name as starting time: " + n);
             } catch (e) {
-                ok(["redirectStart", "redirectEnd", "unloadEventStart", "unloadEventEnd", "loadEventEnd"].indexOf(n) >= 0,
+                ok(["redirectStart", "redirectEnd", "unloadEventStart", "unloadEventEnd", "loadEventEnd", "secureConnectionStart"].indexOf(n) >= 0,
                    "Measure created from reserved name as starting time: " + n + " and threw expected error");
             }
         };
     },
     // TODO: Test measure picking latest version of similarly named tags
 ];
--- a/dom/svg/SVGAElement.h
+++ b/dom/svg/SVGAElement.h
@@ -51,17 +51,17 @@ public:
                               bool aNullParent = true) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual int32_t TabIndexDefault() override;
   virtual bool IsSVGFocusable(bool* aIsFocusable, int32_t* aTabIndex) override;
   virtual bool IsLink(nsIURI** aURI) const override;
   virtual void GetLinkTarget(nsAString& aTarget) override;
   virtual already_AddRefed<nsIURI> GetHrefURI() const override;
   virtual EventStates IntrinsicState() const override;
-  using nsIContent::SetAttr;
+  using Element::SetAttr;
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                            nsAtom* aPrefix, const nsAString& aValue,
                            nsIPrincipal* aSubjectPrincipal,
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
                              bool aNotify) override;
 
   // Link
--- a/dom/svg/SVGStyleElement.h
+++ b/dom/svg/SVGStyleElement.h
@@ -39,17 +39,17 @@ public:
                                            SVGStyleElementBase)
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
-  using nsIContent::SetAttr;
+  using Element::SetAttr;
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                            nsAtom* aPrefix, const nsAString& aValue,
                            nsIPrincipal* aSubjectPrincipal,
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
                              bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/cssB.css
@@ -0,0 +1,2 @@
+@import 'cssC.css';
+@import url('http://example.org/tests/dom/tests/mochitest/general/cssC.css');
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/emptyCssFile2.css
@@ -0,0 +1,1 @@
+@import url('http://example.org/tests/dom/tests/mochitest/general/cross.css');
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/file_resource_timing_nocors.html
@@ -0,0 +1,191 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" href="http://mochi.test:8888/tests/SimpleTest/test.css"/>
+
+  <!--
+    This document has the origin http://mochi.test:8888.
+
+    The resource timing of any all sub-resources should be reported, except for
+    any sub-resources of any cross-origin resources that are loaded.
+
+    Note that the resource timing of the original cross-origin resource should
+    itself be reported.  The goal here is to not reveal which sub-resources are
+    loaded by any cross-origin resources (the fact that any given cross-origin
+    resource itself is loaded is known to the original origin).
+
+    In the comments below, the following annotations apply:
+
+    [r] - this resource should be reported by performance.getEntries()
+    [!] - this resource should be excluded from performance.getEntries()
+  -->
+
+
+  <!-- 1. [r] http://mochi.test:8888 , generateCss.sjs?A
+          [r]   http://mochi.test:8888 , generateCss.sjs?B
+  -->
+  <link rel="stylesheet" type="text/css" href="generateCss.sjs?A"/>
+
+
+  <!-- 2. [r] http://example.com , generateCss.sjs?C
+          [!]   http://example.com , generateCss.sjs?D
+  -->
+  <link rel="stylesheet" type="text/css" href="http://example.com/tests/dom/tests/mochitest/general/generateCss.sjs?C"/>
+
+
+  <!-- 3. [r] http://example.com , generateCss.sjs?E
+          [!]   http://mochi.test:8888 , generateCss.sjs?F
+  -->
+  <link rel="stylesheet" type="text/css" href="http://example.com/tests/dom/tests/mochitest/general/generateCss.sjs?E"/>
+
+
+  <!-- 4. [r] http://mochi.test:8888 , generateCss.sjs?G
+          [r]   http://mochi.test:8888 , generateCss.sjs?H
+          [r]     http://example.com , generateCss.sjs?I
+          [!]       http://example.com , generateCss.sjs?J
+          [r]   http://example.org , generateCss.sjs?K
+          [!]     http://example.org , generateCss.sjs?L
+          [!]       http://example.org , generateCss.sjs?M
+  -->
+  <link rel="stylesheet" type="text/css" href="generateCss.sjs?G"/>
+
+
+  <!-- 5. background-image: -moz-image-rect()
+          [r] http://example.net , generateCss.sjs?N
+          [!]   http://example.net , blue.png
+  -->
+  <link rel="stylesheet" type="text/css" href="http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?N"/>
+
+
+  <!-- 6. background-image: url()
+       [r] http://example.net , generateCss.sjs?O
+       [!]   http://example.net , red.png
+  -->
+  <link rel="stylesheet" type="text/css" href="http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?O"/>
+
+
+  <!-- 7. @font-face
+          [r] http://example.net , generateCss.sjs?P
+          [!]   http://example.net , Ahem.tff
+  -->
+  <link rel="stylesheet" type="text/css" href="http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?P"/>
+
+
+  <!-- 8. cursor: url()
+       [r] http://example.net , generateCss.sjs?Q
+       [!]   http://example.net , over.png
+  -->
+  <link rel="stylesheet" type="text/css" href="http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?Q"/>
+
+
+  <!-- 9. mask: url(res.svg#mask)
+       TODO: I don't think this is working properly. Must fix.
+       [r] http://example.net , generateCss.sjs?R
+       [!]   http://example.net , file_use_counter_svg_fill_pattern_data.svg
+  -->
+  <link rel="stylesheet" type="text/css" href="http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?R"/>
+
+
+  <!-- TODO: add test that we _do_ include subresources if the cross-origin sheet was fetched via CORS -->
+
+
+  <script type="application/javascript">
+
+function ok(cond, message) {
+  window.opener.ok(cond, message)
+}
+
+function is(received, expected, message) {
+  window.opener.is(received, expected, message);
+}
+
+function isnot(received, notExpected, message) {
+  window.opener.isnot(received, notExpected, message);
+}
+
+var allResources = {
+  "http://mochi.test:8888/tests/SimpleTest/test.css" : "link",
+
+  // 1
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/generateCss.sjs?A" : "link",
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/generateCss.sjs?B" : "css",
+
+  // 2
+  "http://example.com/tests/dom/tests/mochitest/general/generateCss.sjs?C" : "link",
+
+  // 3
+  "http://example.com/tests/dom/tests/mochitest/general/generateCss.sjs?E" : "link",
+
+  // 4
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/generateCss.sjs?G" : "link",
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/generateCss.sjs?H" : "css",
+  "http://example.com/tests/dom/tests/mochitest/general/generateCss.sjs?I" : "css",
+  "http://example.org/tests/dom/tests/mochitest/general/generateCss.sjs?K" : "css",
+
+  // 5
+  "http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?N" : "link",
+
+  // 6
+  "http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?O" : "link",
+
+  // 7
+  "http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?P" : "link",
+
+  // 8
+  "http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?Q" : "link",
+
+  // 9
+  "http://example.net/tests/dom/tests/mochitest/general/generateCss.sjs?R" : "link",
+};
+
+window.onload = function() {
+  let entries = performance.getEntries();
+  // The entries.slice() to drop first 'document' item.
+  for (let entry of entries.slice(1)) {
+    //dump(entry.name + " || "+ entry.initiatorType+ "\n");
+    if (!(entry.name in allResources)) {
+      if (entry.name.substr(-4) == ".ttf") {
+        // TODO: fix hiding of font files
+        continue;
+      }
+      ok(false, "Did not expect timing for resource: " + entry.name);
+      continue;
+    }
+    let resType = allResources[entry.name];
+    is(entry.initiatorType, resType,
+       "Expected matching initiatorType for: " + entry.name);
+    delete allResources[entry.name];
+  }
+
+  for (let res in allResources) {
+    ok(false, "Expect timing for resource: " + res);
+  }
+
+  window.opener.finishTests();
+}
+
+</script>
+</head>
+<body>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1180145"
+     title="Resource timing NO-CORS CSS">
+    Bug #1180145 -  Resource Timing NO-CORS CSS
+  </a>
+  <p id="display"></p>
+  <div id="content">
+  </div>
+
+  <div class="c1"> BLUE </div>
+  <div class="c2"> RED  </div>
+  <div class="c3"> Font </div>
+  <div class="c4"> CURSOR </div>
+  <div class="c5"> <img id="image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="> </div>
+  <div class="c6"> </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/generateCss.sjs
@@ -0,0 +1,42 @@
+function handleRequest(request, response) {
+  response.setHeader("Content-Type", "text/css", false);
+  response.write(gResponses[request.queryString]);
+}
+
+let gResponses = {
+  // 1
+  "A": "@import 'generateCss.sjs?B';",
+  "B": "",
+
+  // 2
+  "C": "@import 'generateCss.sjs?D';",
+  "D": "",
+
+  // 3
+  "E": "@import 'generateCss.sjs?F';",
+  "F": "",
+
+  // 4
+  "G": "@import 'generateCss.sjs?H'; @import 'http://example.org/tests/dom/tests/mochitest/general/generateCss.sjs?K';",
+  "H": "@import 'http://example.com/tests/dom/tests/mochitest/general/generateCss.sjs?I';",
+  "I": "@import 'generateCss.sjs?J",
+  "J": "",
+  "K": "@import 'generateCss.sjs?L';",
+  "L": "@import 'generateCss.sjs?M",
+  "M": "",
+
+  // 5
+  "N": ".c1 { background-image: -moz-image-rect(url('/image/test/mochitest/blue.png'), 0, 0, 200, 200);}",
+
+  // 6
+  "O": ".c2 { background-image: url('/image/test/mochitest/red.png');}",
+
+  // 7
+  "P": "@font-face { font-family: Ahem; src: url('/tests/dom/base/test/Ahem.ttf'); } .c3 { font-family: Ahem; font-size: 20px; }",
+
+  // 8
+  "Q": ".c4 { cursor:  url('/image/test/mochitest/over.png') 2 2, auto; } ",
+
+  // 9
+  "R": "#image { mask: url('/tests/dom/base/test/file_use_counter_svg_fill_pattern_data.svg'); }",
+};
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/importsSameAndCrossOrigin.css
@@ -0,0 +1,3 @@
+@import 'emptyCssFile2.css';
+@import url('http://example.org/tests/dom/tests/mochitest/general/emptyCssFile2.css');
+
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -4,16 +4,18 @@ support-files =
   fail.png
   file_bug628069.html
   file_clonewrapper.html
   file_domWindowUtils_scrollbarSize.html
   file_frameElementWrapping.html
   file_interfaces.xml
   file_moving_nodeList.html
   file_moving_xhr.html
+  file_resource_timing_nocors.html
+  generateCss.sjs
   historyframes.html
   start_historyframe.html
   url1_historyframe.html
   url2_historyframe.html
   image_50.png
   image_100.png
   image_200.png
   pass.apng
@@ -51,17 +53,19 @@ support-files =
   storagePermissionsUtils.js
   frameSelectEvents.html
   !/image/test/mochitest/big.png
   !/image/test/mochitest/blue.png
   !/image/test/mochitest/clear.png
   !/image/test/mochitest/damon.jpg
   !/image/test/mochitest/over.png
   !/image/test/mochitest/red.png
+  !/dom/base/test/Ahem.ttf
   !/dom/base/test/file_empty.html
+  !/dom/base/test/file_use_counter_svg_fill_pattern_data.svg
   file_focusrings.html
 
 [test_497898.html]
 skip-if = toolkit == 'android'
 [test_bug504220.html]
 [test_bug628069_1.html]
 [test_bug628069_2.html]
 [test_bug631440.html]
@@ -130,10 +134,11 @@ skip-if = toolkit == 'android' # bug 123
 [test_storagePermissionsLimitForeign.html]
 [test_storagePermissionsReject.html]
 [test_storagePermissionsRejectForeign.html]
 [test_stylesheetPI.html]
 [test_vibrator.html]
 [test_WebKitCSSMatrix.html]
 [test_windowedhistoryframes.html]
 [test_windowProperties.html]
+[test_resource_timing_nocors.html]
 [test_resizeby.html]
 skip-if = toolkit == 'android' # Window sizes cannot be controled on android.
--- a/dom/tests/mochitest/general/resource_timing_main_test.html
+++ b/dom/tests/mochitest/general/resource_timing_main_test.html
@@ -61,28 +61,34 @@ function is(received, expected, message)
 
 function isnot(received, notExpected, message) {
   window.opener.isnot(received, notExpected, message);
 }
 
 var bufferFullCounter = 0;
 const expectedBufferFullEvents = 1;
 
+var allResources = {
+  "http://mochi.test:8888/tests/SimpleTest/test.css": "link",
+  "http://mochi.test:8888/tests/image/test/mochitest/blue.png" : "img",
+  "http://mochi.test:8888/tests/image/test/mochitest/red.png" : "object",
+  "http://mochi.test:8888/tests/image/test/mochitest/big.png" : "embed",
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/resource_timing_iframe.html" : "iframe"};
+
 window.onload = function() {
   ok(!!window.performance, "Performance object should exist");
   ok(!!window.performance.getEntries, "Performance.getEntries() should exist");
   ok(!!window.performance.getEntriesByName, "Performance.getEntriesByName() should exist");
   ok(!!window.performance.getEntriesByType, "Performance.getEntriesByType() should exist");
 
   window.performance.onresourcetimingbufferfull = function() {
     bufferFullCounter += 1;
   }
 
-  // Here, we should have 5 entries (1 css, 3 png, 1 html) since the image was loaded.
-  is(window.performance.getEntriesByType("resource").length, 5, "Performance.getEntriesByType() returned wrong number of entries.");
+  is(window.performance.getEntriesByType("resource").length, Object.keys(allResources).length, "Performance.getEntriesByType() returned wrong number of entries.");
 
   checkStringify(window.performance.getEntriesByType("resource")[0]);
 
   ok(!!window.performance.getEntriesByType("resource").length,
     "Performance.getEntriesByType() should return some results");
   ok(!!window.performance.getEntriesByName("http://mochi.test:8888/tests/image/test/mochitest/blue.png").length,
     "Performance.getEntriesByName() should return some results");
 
@@ -101,21 +107,21 @@ window.onload = function() {
        }
        return true;
      }(window.performance.getEntriesByType("resource"), window.performance.getEntriesByType("resource")),
      "The arrays should have the same entries.");
 
   checkEntries(window.performance.getEntriesByType("resource"));
 
   window.performance.setResourceTimingBufferSize(1);
-  is(window.performance.getEntriesByType("resource").length, 5, "No entries should be " +
+  is(window.performance.getEntriesByType("resource").length, Object.keys(allResources).length, "No entries should be " +
     "removed when setResourceTimingBufferSize is called.");
 
   window.performance.setResourceTimingBufferSize(4);
-  is(window.performance.getEntriesByType("resource").length, 5, "No entries should be " +
+  is(window.performance.getEntriesByType("resource").length, Object.keys(allResources).length, "No entries should be " +
     "removed when setResourceTimingBufferSize is called.");
 
   window.performance.setResourceTimingBufferSize(1);
   window.performance.clearResourceTimings();
   is(window.performance.getEntriesByType("resource").length, 0, "All the entries should " +
     "be removed when when clearResourceTimings is being called.");
 
   makeXhr("test-data.json", firstCheck);
@@ -178,23 +184,16 @@ function checkEntries(anEntryList) {
            ', got ', prevProp, ' = ', entry[prevProp],
           ', ', prop, ' = ', entry[prop]].join(''));
       }
     }
   }
 
   // Check that the entries have the expected initiator type. We can't check
   // the order (the order might depend on the platform the tests are running).
-  allResources = {
-    "http://mochi.test:8888/tests/SimpleTest/test.css" : "link",
-    "http://mochi.test:8888/tests/image/test/mochitest/blue.png" : "img",
-    "http://mochi.test:8888/tests/image/test/mochitest/red.png" : "object",
-    "http://mochi.test:8888/tests/image/test/mochitest/big.png" : "embed",
-    "http://mochi.test:8888/tests/dom/tests/mochitest/general/resource_timing_iframe.html" : "iframe"};
-
   for (resourceName in allResources) {
     // Check that we have a resource with the specific name.
     namedEntries = window.performance.getEntriesByName(resourceName);
     ok (!!namedEntries && (namedEntries.length == 1),
       "An entry with the name '" + resourceName + "' should be available");
 
     if (!namedEntries.length) {
       continue;
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/resource_timing_nocors.html
@@ -0,0 +1,88 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" href="http://mochi.test:8888/tests/SimpleTest/test.css"/>
+  <link rel="stylesheet" type="text/css" href="http://mochi.test:8888/tests/dom/tests/mochitest/general/linkA.css"/>
+  <link rel="stylesheet" type="text/css" href="http://example.com/tests/dom/tests/mochitest/general/linkB.css"/>
+  <link rel="stylesheet" type="text/css" href="http://example.net/tests/dom/tests/mochitest/general/linkC.css"/>
+
+<!--
+
+  Resources fetched by a cross-origin stylesheet loaded with a no-cors mode should not be reported.
+  Resources marked with a ^ should be reported in performance.getEntries()
+
+  (mochi.test:8888 | linkA.css)^ -> (mochi.test:8888 | cssA.css)^
+                                 -> (mochi.test:8888 | cssB.css)^ -> (mochi.test:8888 | cssC.css)^
+                                                                  -> (example.org     | cssC.css)^
+  (example.com     | linkB.css)^ -> (example.com     | cssA.css)
+                                 -> (mochi.test:8888 | cssA.css)
+                                 -> (test2.examp.org | cssB.css) -> (test2.examp.org | cssC.css)
+                                                                 -> (example.org     | cssC.css)
+                                 -> (example.net     | cssC.css)
+
+  (example.net     | linkC.css)^ -> (example.net | cssA.css)
+    [WITH Allow-* HEADERS]
+
+-->
+
+
+  <script type="application/javascript">
+
+function ok(cond, message) {
+  window.opener.ok(cond, message)
+}
+
+function is(received, expected, message) {
+  window.opener.is(received, expected, message);
+}
+
+function isnot(received, notExpected, message) {
+  window.opener.isnot(received, notExpected, message);
+}
+
+var allResources = {
+  "http://mochi.test:8888/tests/SimpleTest/test.css" : "link",
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/linkA.css" : "link",
+  "http://example.com/tests/dom/tests/mochitest/general/linkB.css" : "link",
+  "http://example.net/tests/dom/tests/mochitest/general/linkC.css" : "link",
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/cssA.css" : "css",
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/cssB.css" : "css",
+  "http://mochi.test:8888/tests/dom/tests/mochitest/general/cssC.css" : "css",
+  "http://example.org/tests/dom/tests/mochitest/general/cssC.css" : "css",
+};
+
+window.onload = function() {
+  let entries = performance.getEntries();
+  for (let entry of entries) {
+    let type = allResources[entry.name];
+    if (!type) {
+      ok(false, "Did not expect to find resource: "+entry.name);
+      continue;
+    }
+
+    is(entry.initiatorType, type, "Expected initiatorType does not match");
+  }
+
+  is(entries.length, Object.keys(allResources).length, "Found wrong number of resources");
+
+  window.opener.finishTests();
+}
+
+</script>
+</head>
+<body>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1180145"
+     title="Resource timing NO-CORS CSS">
+    Bug #1180145 -  Resource Timing NO-CORS CSS
+  </a>
+  <p id="display"></p>
+  <div id="content">
+  </div>
+</body>
+</html>
--- a/dom/tests/mochitest/general/test_contentViewer_overrideDPPX.html
+++ b/dom/tests/mochitest/general/test_contentViewer_overrideDPPX.html
@@ -233,26 +233,26 @@ const gTests = {
   "test OverrideDPPX with MediaQueryList": (done) => {
     assertValuesAreInitial();
 
     let promises = [
       new Promise(resolve => {
         let mql = window.matchMedia(`(resolution: ${dppx}dppx)`);
 
         mql.addListener(function listener() {
-          ok("MediaQueryList's listener invoked.")
+          ok(true, "MediaQueryList's listener invoked.")
           mql.removeListener(listener);
           resolve();
         });
       }),
       new Promise(resolve => {
         let mql = frameWindow.matchMedia(`(resolution: ${dppx}dppx)`);
 
         mql.addListener(function listener() {
-          ok("frame's MediaQueryList's listener invoked.")
+          ok(true, "frame's MediaQueryList's listener invoked.")
           mql.removeListener(listener);
           resolve();
         });
       })
     ];
 
     Promise.all(promises)
       .then(() => setOverrideDPPX(0))
@@ -265,17 +265,17 @@ const gTests = {
 
     let overridden = false;
 
     let promises = [
       new Promise(resolve => {
         let mql = window.matchMedia(`(resolution: ${dppx}dppx)`);
 
         mql.addListener(function listener() {
-          ok("MediaQueryList's listener for dppx invoked.");
+          ok(true, "MediaQueryList's listener for dppx invoked.");
           mql.removeListener(listener);
           overridden = true;
           resolve();
         });
       }),
       new Promise(resolve => {
         let mql = window.matchMedia(`(resolution: ${originalDPR * zoom}dppx)`);
 
@@ -284,24 +284,24 @@ const gTests = {
             "MediaQueryList's listener for zoom invoked in the right order");
 
           mql.removeListener(listener);
           resolve();
         });
       })
     ];
 
+    setOverrideDPPX(dppx);
+    setFullZoom(zoom);
+
     promises[0]
       .then(() => setOverrideDPPX(0))
       .then(promises[1])
       .then(() => setFullZoom(originalZoom))
       .then(done, e => {throw e});
-
-    setOverrideDPPX(dppx);
-    setFullZoom(zoom);
   },
   "test OverrideDPPX is kept on document navigation": (done) => {
     assertValuesAreInitial();
 
     let frameOriginalFontSize = getBodyFontSize(frameWindow);
     let frameStyle = createFontStyleForDPPX(frameWindow.document, dppx, "32");
     let frameCurrentFontSize = getBodyFontSize(frameWindow);
 
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/test_resource_timing_nocors.html
@@ -0,0 +1,37 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1180145
+-->
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPrefEnv({"set": [["dom.enable_resource_timing", true]]}, start);
+var subwindow = null;
+
+function start() {
+  subwindow = window.open("file_resource_timing_nocors.html");
+}
+
+function finishTests() {
+  subwindow.close();
+  SimpleTest.finish();
+}
+</script>
+</pre>
+
+</body>
+</html>
--- a/dom/u2f/U2F.cpp
+++ b/dom/u2f/U2F.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/U2F.h"
-#include "mozilla/dom/Event.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/dom/WebAuthnTransactionChild.h"
 #include "nsContentUtils.h"
 #include "nsICryptoHash.h"
 #include "nsIEffectiveTLDService.h"
 #include "nsNetCID.h"
@@ -28,17 +27,16 @@ public:
                                             const nsACString& aOrigHost);
 };
 
 namespace mozilla {
 namespace dom {
 
 static mozilla::LazyLogModule gU2FLog("u2fmanager");
 
-NS_NAMED_LITERAL_STRING(kVisibilityChange, "visibilitychange");
 NS_NAMED_LITERAL_STRING(kFinishEnrollment, "navigator.id.finishEnrollment");
 NS_NAMED_LITERAL_STRING(kGetAssertion, "navigator.id.getAssertion");
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(U2F)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
 NS_INTERFACE_MAP_END
@@ -155,16 +153,33 @@ EvaluateAppID(nsPIDOMWindowInner* aParen
   }
 
   // if the appId URL is not HTTPS, reject.
   bool appIdIsHttps = false;
   if (NS_FAILED(appIdUri->SchemeIs("https", &appIdIsHttps)) || !appIdIsHttps) {
     return ErrorCode::BAD_REQUEST;
   }
 
+  nsAutoCString appIdHost;
+  if (NS_FAILED(appIdUri->GetAsciiHost(appIdHost))) {
+    return ErrorCode::BAD_REQUEST;
+  }
+
+  // Allow localhost.
+  if (appIdHost.EqualsLiteral("localhost")) {
+    nsAutoCString facetHost;
+    if (NS_FAILED(facetUri->GetAsciiHost(facetHost))) {
+      return ErrorCode::BAD_REQUEST;
+    }
+
+    if (facetHost.EqualsLiteral("localhost")) {
+      return ErrorCode::OK;
+    }
+  }
+
   // Run the HTML5 algorithm to relax the same-origin policy, copied from W3C
   // Web Authentication. See Bug 1244959 comment #8 for context on why we are
   // doing this instead of implementing the external-fetch FacetID logic.
   nsCOMPtr<nsIDocument> document = aParent->GetDoc();
   if (!document || !document->IsHTMLDocument()) {
     return ErrorCode::BAD_REQUEST;
   }
   nsHTMLDocument* html = document->AsHTMLDocument();
@@ -179,20 +194,16 @@ EvaluateAppID(nsPIDOMWindowInner* aParen
   if (!tldService) {
     return ErrorCode::BAD_REQUEST;
   }
 
   nsAutoCString lowestFacetHost;
   if (NS_FAILED(tldService->GetBaseDomain(facetUri, 0, lowestFacetHost))) {
     return ErrorCode::BAD_REQUEST;
   }
-  nsAutoCString appIdHost;
-  if (NS_FAILED(appIdUri->GetAsciiHost(appIdHost))) {
-    return ErrorCode::BAD_REQUEST;
-  }
 
   MOZ_LOG(gU2FLog, LogLevel::Debug,
           ("AppId %s Facet %s", appIdHost.get(), lowestFacetHost.get()));
 
   if (html->IsRegistrableDomainSuffixOfOrEqualTo(NS_ConvertUTF8toUTF16(lowestFacetHost),
                                                  appIdHost)) {
     return ErrorCode::OK;
   }
@@ -273,22 +284,16 @@ ExecuteCallback(T& aResp, Maybe<nsMainTh
   NS_WARNING_ASSERTION(!error.Failed(), "dom::U2F::Promise callback failed");
   error.SuppressException(); // Useful exceptions already emitted
 }
 
 /***********************************************************************
  * U2F JavaScript API Implementation
  **********************************************************************/
 
-U2F::U2F(nsPIDOMWindowInner* aParent)
-  : mParent(aParent)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-}
-
 U2F::~U2F()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mTransaction.isSome()) {
     RejectTransaction(NS_ERROR_ABORT);
   }
 
@@ -666,109 +671,10 @@ U2F::RequestAborted(const uint64_t& aTra
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mTransaction.isSome() && mTransaction.ref().mId == aTransactionId) {
     RejectTransaction(aError);
   }
 }
 
-/***********************************************************************
- * Event Handling
- **********************************************************************/
-
-void
-U2F::ListenForVisibilityEvents()
-{
-  nsCOMPtr<nsIDocument> doc = mParent->GetExtantDoc();
-  if (NS_WARN_IF(!doc)) {
-    return;
-  }
-
-  nsresult rv = doc->AddSystemEventListener(kVisibilityChange, this,
-                                            /* use capture */ true,
-                                            /* wants untrusted */ false);
-  Unused << NS_WARN_IF(NS_FAILED(rv));
-}
-
-void
-U2F::StopListeningForVisibilityEvents()
-{
-  nsCOMPtr<nsIDocument> doc = mParent->GetExtantDoc();
-  if (NS_WARN_IF(!doc)) {
-    return;
-  }
-
-  nsresult rv = doc->RemoveSystemEventListener(kVisibilityChange, this,
-                                               /* use capture */ true);
-  Unused << NS_WARN_IF(NS_FAILED(rv));
-}
-
-
-NS_IMETHODIMP
-U2F::HandleEvent(nsIDOMEvent* aEvent)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aEvent);
-
-  nsAutoString type;
-  aEvent->GetType(type);
-  if (!type.Equals(kVisibilityChange)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIDocument> doc =
-    do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
-  if (NS_WARN_IF(!doc)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (doc->Hidden()) {
-    MOZ_LOG(gU2FLog, LogLevel::Debug,
-            ("Visibility change: U2F window is hidden, cancelling job."));
-
-    CancelTransaction(NS_ERROR_ABORT);
-  }
-
-  return NS_OK;
-}
-
-/***********************************************************************
- * IPC Protocol Implementation
- **********************************************************************/
-
-bool
-U2F::MaybeCreateBackgroundActor()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (mChild) {
-    return true;
-  }
-
-  PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
-  if (NS_WARN_IF(!actorChild)) {
-    return false;
-  }
-
-  RefPtr<WebAuthnTransactionChild> mgr(new WebAuthnTransactionChild(this));
-  PWebAuthnTransactionChild* constructedMgr =
-    actorChild->SendPWebAuthnTransactionConstructor(mgr);
-
-  if (NS_WARN_IF(!constructedMgr)) {
-    return false;
-  }
-
-  MOZ_ASSERT(constructedMgr == mgr);
-  mChild = mgr.forget();
-
-  return true;
-}
-
-void
-U2F::ActorDestroyed()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  mChild = nullptr;
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/u2f/U2F.h
+++ b/dom/u2f/U2F.h
@@ -13,24 +13,20 @@
 #include "mozilla/dom/Nullable.h"
 #include "mozilla/dom/U2FBinding.h"
 #include "mozilla/dom/WebAuthnManagerBase.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/MozPromise.h"
 #include "nsProxyRelease.h"
 #include "nsWrapperCache.h"
 #include "U2FAuthenticator.h"
-#include "nsIDOMEventListener.h"
-
-class nsISerialEventTarget;
 
 namespace mozilla {
 namespace dom {
 
-class WebAuthnTransactionChild;
 class U2FRegisterCallback;
 class U2FSignCallback;
 
 // Defined in U2FBinding.h by the U2F.webidl; their use requires a JSContext.
 struct RegisterRequest;
 struct RegisteredKey;
 
 class U2FTransaction
@@ -54,27 +50,26 @@ private:
   // forever, it's sufficient to differentiate between temporally close
   // transactions, where messages can intersect. Can overflow.
   static uint64_t NextId() {
     static uint64_t id = 0;
     return ++id;
   }
 };
 
-class U2F final : public nsIDOMEventListener
-                , public WebAuthnManagerBase
+class U2F final : public WebAuthnManagerBase
                 , public nsWrapperCache
 {
 public:
-  NS_DECL_NSIDOMEVENTLISTENER
-
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(U2F)
 
-  explicit U2F(nsPIDOMWindowInner* aParent);
+  explicit U2F(nsPIDOMWindowInner* aParent)
+    : WebAuthnManagerBase(aParent)
+  { }
 
   nsPIDOMWindowInner*
   GetParentObject() const
   {
     return mParent;
   }
 
   void
@@ -109,45 +104,35 @@ public:
   FinishGetAssertion(const uint64_t& aTransactionId,
                      nsTArray<uint8_t>& aCredentialId,
                      nsTArray<uint8_t>& aSigBuffer) override;
 
   void
   RequestAborted(const uint64_t& aTransactionId,
                  const nsresult& aError) override;
 
-  void ActorDestroyed() override;
+protected:
+  // Cancels the current transaction (by sending a Cancel message to the
+  // parent) and rejects it by calling RejectTransaction().
+  void CancelTransaction(const nsresult& aError) override;
 
 private:
   ~U2F();
 
-  // Visibility event handling.
-  void ListenForVisibilityEvents();
-  void StopListeningForVisibilityEvents();
-
   // Clears all information we have about the current transaction.
   void ClearTransaction();
   // Rejects the current transaction and calls ClearTransaction().
   void RejectTransaction(const nsresult& aError);
-  // Cancels the current transaction (by sending a Cancel message to the
-  // parent) and rejects it by calling RejectTransaction().
-  void CancelTransaction(const nsresult& aError);
-
-  bool MaybeCreateBackgroundActor();
 
   nsString mOrigin;
-  nsCOMPtr<nsPIDOMWindowInner> mParent;
 
   // U2F API callbacks.
   Maybe<nsMainThreadPtrHandle<U2FRegisterCallback>> mRegisterCallback;
   Maybe<nsMainThreadPtrHandle<U2FSignCallback>> mSignCallback;
 
-  // IPC Channel to the parent process.
-  RefPtr<WebAuthnTransactionChild> mChild;
-
   // The current transaction, if any.
   Maybe<U2FTransaction> mTransaction;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_U2F_h
--- a/dom/u2f/tests/browser/browser.ini
+++ b/dom/u2f/tests/browser/browser.ini
@@ -1,6 +1,8 @@
 [DEFAULT]
 support-files =
+  head.js
   tab_u2f_result.html
 skip-if = !e10s
 
 [browser_abort_visibility.js]
+[browser_appid_localhost.js]
--- a/dom/u2f/tests/browser/browser_abort_visibility.js
+++ b/dom/u2f/tests/browser/browser_abort_visibility.js
@@ -1,32 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const TEST_URL = "https://example.com/browser/dom/u2f/tests/browser/tab_u2f_result.html";
 
-function bytesToBase64(u8a){
-  let CHUNK_SZ = 0x8000;
-  let c = [];
-  for (let i = 0; i < u8a.length; i += CHUNK_SZ) {
-    c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));
-  }
-  return window.btoa(c.join(""));
-}
-
-function bytesToBase64UrlSafe(buf) {
-  return bytesToBase64(buf)
-                 .replace(/\+/g, "-")
-                 .replace(/\//g, "_")
-                 .replace(/=/g, "");
-}
-
 async function assertStatus(tab, expected) {
   let actual = await ContentTask.spawn(tab.linkedBrowser, null, async function () {
     return content.document.getElementById("status").value;
   });
   is(actual, expected, "u2f request " + expected);
 }
 
 async function waitForStatus(tab, expected) {
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/browser/browser_appid_localhost.js
@@ -0,0 +1,78 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const TEST_URL = "https://localhost/";
+
+function promiseU2FRegister(tab, app_id) {
+  let challenge = crypto.getRandomValues(new Uint8Array(16));
+  challenge = bytesToBase64UrlSafe(challenge);
+
+  return ContentTask.spawn(tab.linkedBrowser, [app_id, challenge], async function ([app_id, challenge]) {
+    return new Promise(resolve => {
+      let version = "U2F_V2";
+      content.u2f.register(app_id, [{version, challenge}], [], resolve);
+    });
+  });
+}
+
+add_task(async function () {
+  // Enable the soft token.
+  Services.prefs.setBoolPref("security.webauth.u2f", true);
+  Services.prefs.setBoolPref("security.webauth.webauthn_enable_softtoken", true);
+  Services.prefs.setBoolPref("security.webauth.webauthn_enable_usbtoken", false);
+
+  // Open a new tab.
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+
+  // Check that we have the right origin, and U2F is available.
+  let ready = await ContentTask.spawn(tab.linkedBrowser, null, async () => {
+    return content.location.origin == "https://localhost" && content.u2f;
+  });
+  ok(ready, "Origin is https://localhost. U2F is available.");
+
+  // Test: Null AppID
+  await promiseU2FRegister(tab, null).then(res => {
+    is(res.errorCode, 0, "Null AppID should work.");
+  });
+
+  // Test: Empty AppID
+  await promiseU2FRegister(tab, "").then(res => {
+    is(res.errorCode, 0, "Empty AppID should work.");
+  });
+
+  // Test: Correct TLD, incorrect scheme
+  await promiseU2FRegister(tab, "http://localhost/appId").then(res => {
+    isnot(res.errorCode, 0, "Incorrect scheme.");
+  });
+
+  // Test: Incorrect TLD
+  await promiseU2FRegister(tab, "https://localhost.ssl/appId").then(res => {
+    isnot(res.errorCode, 0, "Incorrect TLD.");
+  });
+
+  // Test: Incorrect TLD
+  await promiseU2FRegister(tab, "https://sub.localhost/appId").then(res => {
+    isnot(res.errorCode, 0, "Incorrect TLD.");
+  });
+
+  // Test: Correct TLD
+  await promiseU2FRegister(tab, "https://localhost/appId").then(res => {
+    is(res.errorCode, 0, "https://localhost/appId should work.");
+  });
+
+  // Test: Correct TLD
+  await promiseU2FRegister(tab, "https://localhost:443/appId").then(res => {
+    is(res.errorCode, 0, "https://localhost:443/appId should work.");
+  });
+
+  // Close tab.
+  await BrowserTestUtils.removeTab(tab);
+
+  // Cleanup.
+  Services.prefs.clearUserPref("security.webauth.u2f");
+  Services.prefs.clearUserPref("security.webauth.webauthn_enable_softtoken");
+  Services.prefs.clearUserPref("security.webauth.webauthn_enable_usbtoken");
+});
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/browser/head.js
@@ -0,0 +1,21 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function bytesToBase64(u8a){
+  let CHUNK_SZ = 0x8000;
+  let c = [];
+  for (let i = 0; i < u8a.length; i += CHUNK_SZ) {
+    c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));
+  }
+  return window.btoa(c.join(""));
+}
+
+function bytesToBase64UrlSafe(buf) {
+  return bytesToBase64(buf)
+                 .replace(/\+/g, "-")
+                 .replace(/\//g, "_")
+                 .replace(/=/g, "");
+}
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -37,18 +37,16 @@ const uint8_t FLAG_UV = 0x04; // User wa
 /***********************************************************************
  * Statics
  **********************************************************************/
 
 namespace {
 static mozilla::LazyLogModule gWebAuthnManagerLog("webauthnmanager");
 }
 
-NS_NAMED_LITERAL_STRING(kVisibilityChange, "visibilitychange");
-
 NS_IMPL_ISUPPORTS(WebAuthnManager, nsIDOMEventListener);
 
 /***********************************************************************
  * Utility Functions
  **********************************************************************/
 
 static nsresult
 AssembleClientData(const nsAString& aOrigin, const CryptoBuffer& aChallenge,
@@ -140,54 +138,20 @@ RelaxSameOrigin(nsPIDOMWindowInner* aPar
   if (!html->IsRegistrableDomainSuffixOfOrEqualTo(aInputRpId, originHost)) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   aRelaxedRpId.Assign(NS_ConvertUTF16toUTF8(aInputRpId));
   return NS_OK;
 }
 
-void
-WebAuthnManager::ListenForVisibilityEvents()
-{
-  nsCOMPtr<nsIDocument> doc = mParent->GetExtantDoc();
-  if (NS_WARN_IF(!doc)) {
-    return;
-  }
-
-  nsresult rv = doc->AddSystemEventListener(kVisibilityChange, this,
-                                            /* use capture */ true,
-                                            /* wants untrusted */ false);
-  Unused << NS_WARN_IF(NS_FAILED(rv));
-}
-
-void
-WebAuthnManager::StopListeningForVisibilityEvents()
-{
-  nsCOMPtr<nsIDocument> doc = mParent->GetExtantDoc();
-  if (NS_WARN_IF(!doc)) {
-    return;
-  }
-
-  nsresult rv = doc->RemoveSystemEventListener(kVisibilityChange, this,
-                                               /* use capture */ true);
-  Unused << NS_WARN_IF(NS_FAILED(rv));
-}
-
 /***********************************************************************
  * WebAuthnManager Implementation
  **********************************************************************/
 
-WebAuthnManager::WebAuthnManager(nsPIDOMWindowInner* aParent)
-  : mParent(aParent)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aParent);
-}
-
 void
 WebAuthnManager::ClearTransaction()
 {
   if (!NS_WARN_IF(mTransaction.isNothing())) {
     StopListeningForVisibilityEvents();
   }
 
   mTransaction.reset();
@@ -224,44 +188,16 @@ WebAuthnManager::~WebAuthnManager()
 
   if (mChild) {
     RefPtr<WebAuthnTransactionChild> c;
     mChild.swap(c);
     c->Disconnect();
   }
 }
 
-bool
-WebAuthnManager::MaybeCreateBackgroundActor()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (mChild) {
-    return true;
-  }
-
-  PBackgroundChild* actor = BackgroundChild::GetOrCreateForCurrentThread();
-  if (NS_WARN_IF(!actor)) {
-    return false;
-  }
-
-  RefPtr<WebAuthnTransactionChild> mgr(new WebAuthnTransactionChild(this));
-  PWebAuthnTransactionChild* constructedMgr =
-    actor->SendPWebAuthnTransactionConstructor(mgr);
-
-  if (NS_WARN_IF(!constructedMgr)) {
-    return false;
-  }
-
-  MOZ_ASSERT(constructedMgr == mgr);
-  mChild = mgr.forget();
-
-  return true;
-}
-
 already_AddRefed<Promise>
 WebAuthnManager::MakeCredential(const MakePublicKeyCredentialOptions& aOptions,
                                 const Optional<OwningNonNull<AbortSignal>>& aSignal)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mTransaction.isSome()) {
     CancelTransaction(NS_ERROR_ABORT);
@@ -883,51 +819,16 @@ WebAuthnManager::RequestAborted(const ui
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mTransaction.isSome() && mTransaction.ref().mId == aTransactionId) {
     RejectTransaction(aError);
   }
 }
 
-NS_IMETHODIMP
-WebAuthnManager::HandleEvent(nsIDOMEvent* aEvent)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aEvent);
-
-  nsAutoString type;
-  aEvent->GetType(type);
-  if (!type.Equals(kVisibilityChange)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIDocument> doc =
-    do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
-  if (NS_WARN_IF(!doc)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (doc->Hidden()) {
-    MOZ_LOG(gWebAuthnManagerLog, LogLevel::Debug,
-            ("Visibility change: WebAuthn window is hidden, cancelling job."));
-
-    CancelTransaction(NS_ERROR_ABORT);
-  }
-
-  return NS_OK;
-}
-
 void
 WebAuthnManager::Abort()
 {
   CancelTransaction(NS_ERROR_DOM_ABORT_ERR);
 }
 
-void
-WebAuthnManager::ActorDestroyed()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  mChild = nullptr;
-}
-
 }
 }
--- a/dom/webauthn/WebAuthnManager.h
+++ b/dom/webauthn/WebAuthnManager.h
@@ -3,20 +3,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_WebAuthnManager_h
 #define mozilla_dom_WebAuthnManager_h
 
 #include "mozilla/MozPromise.h"
-#include "mozilla/dom/Event.h"
 #include "mozilla/dom/PWebAuthnTransaction.h"
 #include "mozilla/dom/WebAuthnManagerBase.h"
-#include "nsIDOMEventListener.h"
 
 /*
  * Content process manager for the WebAuthn protocol. Created on calls to the
  * WebAuthentication DOM object, this manager handles establishing IPC channels
  * for WebAuthn transactions, as well as keeping track of JS Promise objects
  * representing transactions in flight.
  *
  * The WebAuthn spec (https://www.w3.org/TR/webauthn/) allows for two different
@@ -48,24 +46,16 @@ class nsHTMLDocument {
 public:
   bool IsRegistrableDomainSuffixOfOrEqualTo(const nsAString& aHostSuffixString,
                                             const nsACString& aOrigHost);
 };
 
 namespace mozilla {
 namespace dom {
 
-struct Account;
-class ArrayBufferViewOrArrayBuffer;
-struct AssertionOptions;
-class OwningArrayBufferViewOrArrayBuffer;
-struct MakePublicKeyCredentialOptions;
-class Promise;
-class WebAuthnTransactionChild;
-
 class WebAuthnTransaction
 {
 public:
   WebAuthnTransaction(const RefPtr<Promise>& aPromise,
                       const nsTArray<uint8_t>& aRpIdHash,
                       const nsCString& aClientData,
                       AbortSignal* aSignal)
     : mPromise(aPromise)
@@ -98,24 +88,24 @@ private:
   // transactions, where messages can intersect. Can overflow.
   static uint64_t NextId() {
     static uint64_t id = 0;
     return ++id;
   }
 };
 
 class WebAuthnManager final : public WebAuthnManagerBase
-                            , public nsIDOMEventListener
                             , public AbortFollower
 {
 public:
   NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMEVENTLISTENER
 
-  explicit WebAuthnManager(nsPIDOMWindowInner* aParent);
+  explicit WebAuthnManager(nsPIDOMWindowInner* aParent)
+    : WebAuthnManagerBase(aParent)
+  { }
 
   already_AddRefed<Promise>
   MakeCredential(const MakePublicKeyCredentialOptions& aOptions,
                  const Optional<OwningNonNull<AbortSignal>>& aSignal);
 
   already_AddRefed<Promise>
   GetAssertion(const PublicKeyCredentialRequestOptions& aOptions,
                const Optional<OwningNonNull<AbortSignal>>& aSignal);
@@ -133,44 +123,32 @@ public:
   FinishGetAssertion(const uint64_t& aTransactionId,
                      nsTArray<uint8_t>& aCredentialId,
                      nsTArray<uint8_t>& aSigBuffer) override;
 
   void
   RequestAborted(const uint64_t& aTransactionId,
                  const nsresult& aError) override;
 
-  void ActorDestroyed() override;
-
   // AbortFollower
 
   void Abort() override;
 
+protected:
+  // Cancels the current transaction (by sending a Cancel message to the
+  // parent) and rejects it by calling RejectTransaction().
+  void CancelTransaction(const nsresult& aError) override;
+
 private:
   virtual ~WebAuthnManager();
 
-  // Visibility event handling.
-  void ListenForVisibilityEvents();
-  void StopListeningForVisibilityEvents();
-
   // Clears all information we have about the current transaction.
   void ClearTransaction();
   // Rejects the current transaction and calls ClearTransaction().
   void RejectTransaction(const nsresult& aError);
-  // Cancels the current transaction (by sending a Cancel message to the
-  // parent) and rejects it by calling RejectTransaction().
-  void CancelTransaction(const nsresult& aError);
-
-  bool MaybeCreateBackgroundActor();
-
-  // The parent window.
-  nsCOMPtr<nsPIDOMWindowInner> mParent;
-
-  // IPC Channel to the parent process.
-  RefPtr<WebAuthnTransactionChild> mChild;
 
   // The current transaction, if any.
   Maybe<WebAuthnTransaction> mTransaction;
 };
 
 } // namespace dom
 } // namespace mozilla
 
new file mode 100644
--- /dev/null
+++ b/dom/webauthn/WebAuthnManagerBase.cpp
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/WebAuthnManagerBase.h"
+#include "mozilla/dom/WebAuthnTransactionChild.h"
+#include "mozilla/dom/Event.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_NAMED_LITERAL_STRING(kVisibilityChange, "visibilitychange");
+
+WebAuthnManagerBase::WebAuthnManagerBase(nsPIDOMWindowInner* aParent)
+  : mParent(aParent)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aParent);
+}
+
+WebAuthnManagerBase::~WebAuthnManagerBase()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+/***********************************************************************
+ * IPC Protocol Implementation
+ **********************************************************************/
+
+bool
+WebAuthnManagerBase::MaybeCreateBackgroundActor()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (mChild) {
+    return true;
+  }
+
+  PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
+  if (NS_WARN_IF(!actorChild)) {
+    return false;
+  }
+
+  RefPtr<WebAuthnTransactionChild> mgr(new WebAuthnTransactionChild(this));
+  PWebAuthnTransactionChild* constructedMgr =
+    actorChild->SendPWebAuthnTransactionConstructor(mgr);
+
+  if (NS_WARN_IF(!constructedMgr)) {
+    return false;
+  }
+
+  MOZ_ASSERT(constructedMgr == mgr);
+  mChild = mgr.forget();
+
+  return true;
+}
+
+void
+WebAuthnManagerBase::ActorDestroyed()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mChild = nullptr;
+}
+
+/***********************************************************************
+ * Event Handling
+ **********************************************************************/
+
+void
+WebAuthnManagerBase::ListenForVisibilityEvents()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIDocument> doc = mParent->GetExtantDoc();
+  if (NS_WARN_IF(!doc)) {
+    return;
+  }
+
+  nsresult rv = doc->AddSystemEventListener(kVisibilityChange, this,
+                                            /* use capture */ true,
+                                            /* wants untrusted */ false);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+}
+
+void
+WebAuthnManagerBase::StopListeningForVisibilityEvents()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIDocument> doc = mParent->GetExtantDoc();
+  if (NS_WARN_IF(!doc)) {
+    return;
+  }
+
+  nsresult rv = doc->RemoveSystemEventListener(kVisibilityChange, this,
+                                               /* use capture */ true);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+}
+
+NS_IMETHODIMP
+WebAuthnManagerBase::HandleEvent(nsIDOMEvent* aEvent)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aEvent);
+
+  nsAutoString type;
+  aEvent->GetType(type);
+  if (!type.Equals(kVisibilityChange)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIDocument> doc =
+    do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
+  if (NS_WARN_IF(!doc)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (doc->Hidden()) {
+    CancelTransaction(NS_ERROR_ABORT);
+  }
+
+  return NS_OK;
+}
+
+}
+}
--- a/dom/webauthn/WebAuthnManagerBase.h
+++ b/dom/webauthn/WebAuthnManagerBase.h
@@ -2,39 +2,65 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_WebAuthnManagerBase_h
 #define mozilla_dom_WebAuthnManagerBase_h
 
+#include "nsIDOMEventListener.h"
+
 /*
  * A base class used by WebAuthn and U2F implementations, providing shared
  * functionality and requiring an interface used by the IPC child actors.
  */
 
 namespace mozilla {
 namespace dom {
 
-class WebAuthnManagerBase
+class WebAuthnTransactionChild;
+
+class WebAuthnManagerBase : public nsIDOMEventListener
 {
 public:
+  NS_DECL_NSIDOMEVENTLISTENER
+
+  explicit WebAuthnManagerBase(nsPIDOMWindowInner* aParent);
+
   virtual void
   FinishMakeCredential(const uint64_t& aTransactionId,
                        nsTArray<uint8_t>& aRegBuffer) = 0;
 
   virtual void
   FinishGetAssertion(const uint64_t& aTransactionId,
                      nsTArray<uint8_t>& aCredentialId,
                      nsTArray<uint8_t>& aSigBuffer) = 0;
 
   virtual void
   RequestAborted(const uint64_t& aTransactionId,
                  const nsresult& aError) = 0;
 
-  virtual void ActorDestroyed() = 0;
+  void ActorDestroyed();
+
+protected:
+  ~WebAuthnManagerBase();
+
+  // Needed by HandleEvent() to cancel transactions.
+  virtual void CancelTransaction(const nsresult& aError) = 0;
+
+  // Visibility event handling.
+  void ListenForVisibilityEvents();
+  void StopListeningForVisibilityEvents();
+
+  bool MaybeCreateBackgroundActor();
+
+  // The parent window.
+  nsCOMPtr<nsPIDOMWindowInner> mParent;
+
+  // IPC Channel to the parent process.
+  RefPtr<WebAuthnTransactionChild> mChild;
 };
 
 }
 }
 
 #endif //mozilla_dom_WebAuthnManagerBase_h
--- a/dom/webauthn/moz.build
+++ b/dom/webauthn/moz.build
@@ -35,16 +35,17 @@ UNIFIED_SOURCES += [
     'cbor-cpp/src/encoder.cpp',
     'cbor-cpp/src/output_dynamic.cpp',
     'PublicKeyCredential.cpp',
     'U2FHIDTokenManager.cpp',
     'U2FSoftTokenManager.cpp',
     'U2FTokenManager.cpp',
     'WebAuthnCBORUtil.cpp',
     'WebAuthnManager.cpp',
+    'WebAuthnManagerBase.cpp',
     'WebAuthnTransactionChild.cpp',
     'WebAuthnTransactionParent.cpp',
     'WebAuthnUtil.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -257,17 +257,17 @@ nsXBLBinding::UnbindAnonymousContent(nsI
     if (xuldoc) {
       xuldoc->RemoveSubtreeFromDocument(child);
     }
 #endif
   }
 }
 
 void
-nsXBLBinding::SetBoundElement(nsIContent* aElement)
+nsXBLBinding::SetBoundElement(Element* aElement)
 {
   mBoundElement = aElement;
   if (mNextBinding)
     mNextBinding->SetBoundElement(aElement);
 
   if (!mBoundElement) {
     return;
   }
@@ -296,17 +296,17 @@ nsXBLBinding::HasStyleSheets() const
 
 void
 nsXBLBinding::GenerateAnonymousContent()
 {
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                "Someone forgot a script blocker");
 
   // Fetch the content element for this binding.
-  nsIContent* content =
+  Element* content =
     mPrototypeBinding->GetImmediateChild(nsGkAtoms::content);
 
   if (!content) {
     // We have no anonymous content.
     if (mNextBinding)
       mNextBinding->GenerateAnonymousContent();
 
     return;
@@ -412,18 +412,22 @@ nsXBLBinding::GenerateAnonymousContent()
         nsAutoString value2;
         attrInfo.mValue->ToString(value2);
         mBoundElement->SetAttr(namespaceID, name, attrInfo.mName->GetPrefix(),
                                value2, false);
       }
     }
 
     // Conserve space by wiping the attributes off the clone.
+    //
+    // FIXME(emilio): It'd be nice to make `mContent` a `RefPtr<Element>`, but
+    // as of right now it can also be a ShadowRoot (we don't enter in this
+    // codepath though). Move Shadow DOM outside XBL and then fix that.
     if (mContent)
-      mContent->UnsetAttr(namespaceID, name, false);
+      mContent->AsElement()->UnsetAttr(namespaceID, name, false);
   }
 }
 
 nsIURI*
 nsXBLBinding::GetSourceDocURI()
 {
   nsIContent* targetContent =
     mPrototypeBinding->GetImmediateChild(nsGkAtoms::content);
--- a/dom/xbl/nsXBLBinding.h
+++ b/dom/xbl/nsXBLBinding.h
@@ -59,18 +59,18 @@ public:
 
   nsXBLPrototypeBinding* PrototypeBinding() const { return mPrototypeBinding; }
   nsIContent* GetAnonymousContent() { return mContent.get(); }
   nsXBLBinding* GetBindingWithContent();
 
   nsXBLBinding* GetBaseBinding() const { return mNextBinding; }
   void SetBaseBinding(nsXBLBinding *aBinding);
 
-  nsIContent* GetBoundElement() { return mBoundElement; }
-  void SetBoundElement(nsIContent *aElement);
+  mozilla::dom::Element* GetBoundElement() { return mBoundElement; }
+  void SetBoundElement(mozilla::dom::Element* aElement);
 
   /*
    * Does a lookup for a method or attribute provided by one of the bindings'
    * prototype implementation. If found, |desc| will be set up appropriately,
    * and wrapped into cx->compartment.
    *
    * May only be called when XBL code is being run in a separate scope, because
    * otherwise we don't have untainted data with which to do a proper lookup.
@@ -168,17 +168,17 @@ protected:
   bool mMarkedForDeath;
   bool mUsingContentXBLScope;
   bool mIsShadowRootBinding;
 
   nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo
   nsCOMPtr<nsIContent> mContent; // Strong. Our anonymous content stays around with us.
   RefPtr<nsXBLBinding> mNextBinding; // Strong. The derived binding owns the base class bindings.
 
-  nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
+  mozilla::dom::Element* mBoundElement; // [WEAK] We have a reference, but we don't own it.
 
   // The <xbl:children> elements that we found in our <xbl:content> when we
   // processed this binding. The default insertion point has no includes
   // attribute and all other insertion points must have at least one includes
   // attribute. These points must be up-to-date with respect to their parent's
   // children, even if their parent has another binding attached to it,
   // preventing us from rendering their contents directly.
   RefPtr<mozilla::dom::XBLChildrenElement> mDefaultInsertionPoint;
--- a/dom/xbl/nsXBLContentSink.cpp
+++ b/dom/xbl/nsXBLContentSink.cpp
@@ -530,17 +530,18 @@ nsXBLContentSink::OnOpenContainer(const 
   return ret && mState != eXBL_InResources && mState != eXBL_InImplementation;
 }
 
 #undef ENSURE_XBL_STATE
 
 nsresult
 nsXBLContentSink::ConstructBinding(uint32_t aLineNumber)
 {
-  nsCOMPtr<nsIContent> binding = GetCurrentContent();
+  // This is only called from HandleStartElement, so it'd better be an element.
+  RefPtr<Element> binding = GetCurrentContent()->AsElement();
   binding->GetAttr(kNameSpaceID_None, nsGkAtoms::id, mCurrentBindingID);
   NS_ConvertUTF16toUTF8 cid(mCurrentBindingID);
 
   nsresult rv = NS_OK;
 
   // Don't create a binding with no id. nsXBLPrototypeBinding::Read also
   // performs this check.
   if (!cid.IsEmpty()) {
@@ -875,23 +876,22 @@ nsXBLContentSink::CreateElement(const ch
   Element* result;
   nsresult rv = nsXULElement::Create(prototype, mDocument, false, false, &result);
   *aResult = result;
   return rv;
 #endif
 }
 
 nsresult
-nsXBLContentSink::AddAttributes(const char16_t** aAtts,
-                                nsIContent* aContent)
+nsXBLContentSink::AddAttributes(const char16_t** aAtts, Element* aElement)
 {
-  if (aContent->IsXULElement())
+  if (aElement->IsXULElement())
     return NS_OK; // Nothing to do, since the proto already has the attrs.
 
-  return nsXMLContentSink::AddAttributes(aAtts, aContent);
+  return nsXMLContentSink::AddAttributes(aAtts, aElement);
 }
 
 #ifdef MOZ_XUL
 nsresult
 nsXBLContentSink::AddAttributesToXULPrototype(const char16_t **aAtts,
                                               uint32_t aAttsCount,
                                               nsXULPrototypeElement* aElement)
 {
--- a/dom/xbl/nsXBLContentSink.h
+++ b/dom/xbl/nsXBLContentSink.h
@@ -87,18 +87,17 @@ protected:
 
     bool NotifyForDocElement() override { return false; }
 
     nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
                            mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
                            nsIContent** aResult, bool* aAppendContent,
                            mozilla::dom::FromParser aFromParser) override;
 
-    nsresult AddAttributes(const char16_t** aAtts,
-                           nsIContent* aContent) override;
+    nsresult AddAttributes(const char16_t** aAtts, Element* aElement) override;
 
 #ifdef MOZ_XUL
     nsresult AddAttributesToXULPrototype(const char16_t **aAtts,
                                          uint32_t aAttsCount,
                                          nsXULPrototypeElement* aElement);
 #endif
 
     // Our own helpers for constructing XBL prototype objects.
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -57,38 +57,38 @@ using namespace mozilla::dom;
 // Helper Classes =====================================================================
 
 // nsXBLAttributeEntry and helpers.  This class is used to efficiently handle
 // attribute changes in anonymous content.
 
 class nsXBLAttributeEntry {
 public:
   nsXBLAttributeEntry(nsAtom* aSrcAtom, nsAtom* aDstAtom,
-                      int32_t aDstNameSpace, nsIContent* aContent)
-    : mElement(aContent),
+                      int32_t aDstNameSpace, Element* aElement)
+    : mElement(aElement),
       mSrcAttribute(aSrcAtom),
       mDstAttribute(aDstAtom),
       mDstNameSpace(aDstNameSpace),
       mNext(nullptr) { }
 
   ~nsXBLAttributeEntry() {
     NS_CONTENT_DELETE_LIST_MEMBER(nsXBLAttributeEntry, this, mNext);
   }
 
   nsAtom* GetSrcAttribute() { return mSrcAttribute; }
   nsAtom* GetDstAttribute() { return mDstAttribute; }
   int32_t GetDstNameSpace() { return mDstNameSpace; }
 
-  nsIContent* GetElement() { return mElement; }
+  Element* GetElement() { return mElement; }
 
   nsXBLAttributeEntry* GetNext() { return mNext; }
   void SetNext(nsXBLAttributeEntry* aEntry) { mNext = aEntry; }
 
 protected:
-  nsIContent* mElement;
+  Element* mElement;
 
   RefPtr<nsAtom> mSrcAttribute;
   RefPtr<nsAtom> mDstAttribute;
   int32_t mDstNameSpace;
   nsXBLAttributeEntry* mNext;
 };
 
 // =============================================================================
@@ -108,17 +108,17 @@ nsXBLPrototypeBinding::nsXBLPrototypeBin
   mBaseNameSpaceID(kNameSpaceID_None)
 {
   MOZ_COUNT_CTOR(nsXBLPrototypeBinding);
 }
 
 nsresult
 nsXBLPrototypeBinding::Init(const nsACString& aID,
                             nsXBLDocumentInfo* aInfo,
-                            nsIContent* aElement,
+                            Element* aElement,
                             bool aFirstBinding)
 {
   nsresult rv = aInfo->DocumentURI()->Clone(getter_AddRefs(mBindingURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The binding URI might be an immutable URI (e.g. for about: URIs). In that case,
   // we'll fail in SetRef below, but that doesn't matter much for now.
   if (aFirstBinding) {
@@ -175,18 +175,17 @@ nsXBLPrototypeBinding::Trace(const Trace
 {
   if (mImplementation)
     mImplementation->Trace(aCallbacks, aClosure);
 }
 
 void
 nsXBLPrototypeBinding::Initialize()
 {
-  nsIContent* content = GetImmediateChild(nsGkAtoms::content);
-  if (content) {
+  if (Element* content = GetImmediateChild(nsGkAtoms::content)) {
     ConstructAttributeTable(content);
   }
 }
 
 nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
 {
   delete mImplementation;
   MOZ_COUNT_DTOR(nsXBLPrototypeBinding);
@@ -202,17 +201,17 @@ nsXBLPrototypeBinding::SetBasePrototype(
     NS_ERROR("Base XBL prototype binding is already defined!");
     return;
   }
 
   mBaseBinding = aBinding;
 }
 
 void
-nsXBLPrototypeBinding::SetBindingElement(nsIContent* aElement)
+nsXBLPrototypeBinding::SetBindingElement(Element* aElement)
 {
   mBinding = aElement;
   if (mBinding->AttrValueIs(kNameSpaceID_None, nsGkAtoms::inheritstyle,
                             nsGkAtoms::_false, eCaseMatters))
     mInheritStyle = false;
 
   mChromeOnlyContent = mBinding->AttrValueIs(kNameSpaceID_None,
                                              nsGkAtoms::chromeOnlyContent,
@@ -318,39 +317,38 @@ nsXBLPrototypeBinding::InstallImplementa
   return NS_OK;
 }
 
 // XXXbz this duplicates lots of SetAttrs
 void
 nsXBLPrototypeBinding::AttributeChanged(nsAtom* aAttribute,
                                         int32_t aNameSpaceID,
                                         bool aRemoveFlag,
-                                        nsIContent* aChangedElement,
+                                        Element* aChangedElement,
                                         nsIContent* aAnonymousContent,
                                         bool aNotify)
 {
   if (!mAttributeTable)
     return;
 
   InnerAttributeTable *attributesNS = mAttributeTable->Get(aNameSpaceID);
   if (!attributesNS)
     return;
 
   nsXBLAttributeEntry* xblAttr = attributesNS->Get(aAttribute);
   if (!xblAttr)
     return;
 
   // Iterate over the elements in the array.
-  nsCOMPtr<nsIContent> content = GetImmediateChild(nsGkAtoms::content);
+  RefPtr<Element> content = GetImmediateChild(nsGkAtoms::content);
   while (xblAttr) {
-    nsIContent* element = xblAttr->GetElement();
+    Element* element = xblAttr->GetElement();
 
-    nsCOMPtr<nsIContent> realElement = LocateInstance(aChangedElement, content,
-                                                      aAnonymousContent,
-                                                      element);
+    RefPtr<Element> realElement =
+      LocateInstance(aChangedElement, content, aAnonymousContent, element);
 
     if (realElement) {
       // Hold a strong reference here so that the atom doesn't go away during
       // UnsetAttr.
       RefPtr<nsAtom> dstAttr = xblAttr->GetDstAttribute();
       int32_t dstNs = xblAttr->GetDstNameSpace();
 
       if (aRemoveFlag)
@@ -431,24 +429,24 @@ bool
 nsXBLPrototypeBinding::ImplementsInterface(REFNSIID aIID) const
 {
   // Check our IID table.
   return !!mInterfaceTable.GetWeak(aIID);
 }
 
 // Internal helpers ///////////////////////////////////////////////////////////////////////
 
-nsIContent*
+Element*
 nsXBLPrototypeBinding::GetImmediateChild(nsAtom* aTag)
 {
   for (nsIContent* child = mBinding->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->NodeInfo()->Equals(aTag, kNameSpaceID_XBL)) {
-      return child;
+      return child->AsElement();
     }
   }
 
   return nullptr;
 }
 
 nsresult
 nsXBLPrototypeBinding::InitClass(const nsString& aClassName,
@@ -456,45 +454,51 @@ nsXBLPrototypeBinding::InitClass(const n
                                  JS::Handle<JSObject*> aScriptObject,
                                  JS::MutableHandle<JSObject*> aClassObject,
                                  bool* aNew)
 {
   return nsXBLBinding::DoInitJSClass(aContext, aScriptObject,
                                      aClassName, this, aClassObject, aNew);
 }
 
-nsIContent*
-nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement,
+Element*
+nsXBLPrototypeBinding::LocateInstance(Element* aBoundElement,
                                       nsIContent* aTemplRoot,
                                       nsIContent* aCopyRoot,
-                                      nsIContent* aTemplChild)
+                                      Element* aTemplChild)
 {
   // XXX We will get in trouble if the binding instantiation deviates from the template
   // in the prototype.
   if (aTemplChild == aTemplRoot || !aTemplChild)
     return nullptr;
 
-  nsIContent* templParent = aTemplChild->GetParent();
+  Element* templParent = aTemplChild->GetParentElement();
 
   // We may be disconnected from our parent during cycle collection.
   if (!templParent)
     return nullptr;
 
   nsIContent *copyParent =
     templParent == aTemplRoot ? aCopyRoot :
                    LocateInstance(aBoundElement, aTemplRoot, aCopyRoot, templParent);
 
   if (!copyParent)
     return nullptr;
 
-  return copyParent->GetChildAt(templParent->IndexOf(aTemplChild));
+  nsIContent* child = copyParent->GetChildAt(templParent->IndexOf(aTemplChild));
+  if (child && child->IsElement()) {
+    return child->AsElement();
+  }
+  return nullptr;
 }
 
 void
-nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent)
+nsXBLPrototypeBinding::SetInitialAttributes(
+    Element* aBoundElement,
+    nsIContent* aAnonymousContent)
 {
   if (!mAttributeTable) {
     return;
   }
 
   for (auto iter1 = mAttributeTable->Iter(); !iter1.Done(); iter1.Next()) {
     InnerAttributeTable* xblAttributes = iter1.UserData();
     if (xblAttributes) {
@@ -523,19 +527,19 @@ nsXBLPrototypeBinding::SetInitialAttribu
 
         if (attrPresent) {
           nsIContent* content = GetImmediateChild(nsGkAtoms::content);
 
           nsXBLAttributeEntry* curr = entry;
           while (curr) {
             nsAtom* dst = curr->GetDstAttribute();
             int32_t dstNs = curr->GetDstNameSpace();
-            nsIContent* element = curr->GetElement();
+            Element* element = curr->GetElement();
 
-            nsIContent* realElement =
+            Element* realElement =
               LocateInstance(aBoundElement, content,
                              aAnonymousContent, element);
 
             if (realElement) {
               realElement->SetAttr(dstNs, dst, value, false);
 
               // XXXndeakin shouldn't this be done in lieu of SetAttr?
               if ((dst == nsGkAtoms::text && dstNs == kNameSpaceID_XBL) ||
@@ -590,39 +594,39 @@ nsXBLPrototypeBinding::EnsureAttributeTa
     mAttributeTable =
         new nsClassHashtable<nsUint32HashKey, InnerAttributeTable>(2);
   }
 }
 
 void
 nsXBLPrototypeBinding::AddToAttributeTable(int32_t aSourceNamespaceID, nsAtom* aSourceTag,
                                            int32_t aDestNamespaceID, nsAtom* aDestTag,
-                                           nsIContent* aContent)
+                                           Element* aElement)
 {
     InnerAttributeTable* attributesNS = mAttributeTable->Get(aSourceNamespaceID);
     if (!attributesNS) {
       attributesNS = new InnerAttributeTable(2);
       mAttributeTable->Put(aSourceNamespaceID, attributesNS);
     }
 
     nsXBLAttributeEntry* xblAttr =
-      new nsXBLAttributeEntry(aSourceTag, aDestTag, aDestNamespaceID, aContent);
+      new nsXBLAttributeEntry(aSourceTag, aDestTag, aDestNamespaceID, aElement);
 
     nsXBLAttributeEntry* entry = attributesNS->Get(aSourceTag);
     if (!entry) {
       attributesNS->Put(aSourceTag, xblAttr);
     } else {
       while (entry->GetNext())
         entry = entry->GetNext();
       entry->SetNext(xblAttr);
     }
 }
 
 void
-nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
+nsXBLPrototypeBinding::ConstructAttributeTable(Element* aElement)
 {
   // Don't add entries for <children> elements, since those will get
   // removed from the DOM when we construct the insertion point table.
   if (!aElement->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
     nsAutoString inherits;
     aElement->GetAttr(kNameSpaceID_XBL, nsGkAtoms::inherits, inherits);
 
     if (!inherits.IsEmpty()) {
@@ -687,17 +691,19 @@ nsXBLPrototypeBinding::ConstructAttribut
       free(str);
     }
   }
 
   // Recur into our children.
   for (nsIContent* child = aElement->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
-    ConstructAttributeTable(child);
+    if (child->IsElement()) {
+      ConstructAttributeTable(child->AsElement());
+    }
   }
 }
 
 nsresult
 nsXBLPrototypeBinding::ConstructInterfaceTable(const nsAString& aImpls)
 {
   if (!aImpls.IsEmpty()) {
     // Obtain the interface info manager that can tell us the IID
@@ -1190,22 +1196,21 @@ nsXBLPrototypeBinding::ReadContentNode(n
   int32_t namespaceID;
   nsresult rv = ReadNamespace(aStream, namespaceID);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // There is no content to read so just return.
   if (namespaceID == XBLBinding_Serialize_NoContent)
     return NS_OK;
 
-  nsCOMPtr<nsIContent> content;
-
   // If this is a text type, just read the string and return.
   if (namespaceID == XBLBinding_Serialize_TextNode ||
       namespaceID == XBLBinding_Serialize_CDATANode ||
       namespaceID == XBLBinding_Serialize_CommentNode) {
+    nsCOMPtr<nsIContent> content;
     switch (namespaceID) {
       case XBLBinding_Serialize_TextNode:
         content = new nsTextNode(aNim);
         break;
       case XBLBinding_Serialize_CDATANode:
         content = new CDATASection(aNim);
         break;
       case XBLBinding_Serialize_CommentNode:
@@ -1239,16 +1244,17 @@ nsXBLPrototypeBinding::ReadContentNode(n
   RefPtr<nsAtom> tagAtom = NS_Atomize(tag);
   RefPtr<NodeInfo> nodeInfo =
     aNim->GetNodeInfo(tagAtom, prefixAtom, namespaceID, nsIDOMNode::ELEMENT_NODE);
 
   uint32_t attrCount;
   rv = aStream->Read32(&attrCount);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  RefPtr<Element> element;
   // Create XUL prototype elements, or regular elements for other namespaces.
   // This needs to match the code in nsXBLContentSink::CreateElement.
 #ifdef MOZ_XUL
   if (namespaceID == kNameSpaceID_XUL) {
     nsIURI* documentURI = aDocument->GetDocumentURI();
 
     RefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement();
 
@@ -1288,27 +1294,22 @@ nsXBLPrototypeBinding::ReadContentNode(n
                             namespaceID, nsIDOMNode::ATTRIBUTE_NODE);
         attrs[i].mName.SetTo(ni);
       }
 
       rv = prototype->SetAttrAt(i, val, documentURI);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    nsCOMPtr<Element> result;
     nsresult rv =
-      nsXULElement::Create(prototype, aDocument, false, false, getter_AddRefs(result));
+      nsXULElement::Create(prototype, aDocument, false, false, getter_AddRefs(element));
     NS_ENSURE_SUCCESS(rv, rv);
-    content = result;
-  }
-  else {
+  } else {
 #endif
-    nsCOMPtr<Element> element;
     NS_NewElement(getter_AddRefs(element), nodeInfo.forget(), NOT_FROM_PARSER);
-    content = element;
 
     for (uint32_t i = 0; i < attrCount; i++) {
       rv = ReadNamespace(aStream, namespaceID);
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsAutoString prefix, name, val;
       rv = aStream->ReadString(prefix);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -1317,17 +1318,17 @@ nsXBLPrototypeBinding::ReadContentNode(n
       rv = aStream->ReadString(val);
       NS_ENSURE_SUCCESS(rv, rv);
 
       RefPtr<nsAtom> prefixAtom;
       if (!prefix.IsEmpty())
         prefixAtom = NS_Atomize(prefix);
 
       RefPtr<nsAtom> nameAtom = NS_Atomize(name);
-      content->SetAttr(namespaceID, nameAtom, prefixAtom, val, false);
+      element->SetAttr(namespaceID, nameAtom, prefixAtom, val, false);
     }
 
 #ifdef MOZ_XUL
   }
 #endif
 
   // Now read the attribute forwarding entries (xbl:inherits)
 
@@ -1343,38 +1344,38 @@ nsXBLPrototypeBinding::ReadContentNode(n
     NS_ENSURE_SUCCESS(rv, rv);
     rv = aStream->ReadString(destAttribute);
     NS_ENSURE_SUCCESS(rv, rv);
 
     RefPtr<nsAtom> srcAtom = NS_Atomize(srcAttribute);
     RefPtr<nsAtom> destAtom = NS_Atomize(destAttribute);
 
     EnsureAttributeTable();
-    AddToAttributeTable(srcNamespaceID, srcAtom, destNamespaceID, destAtom, content);
+    AddToAttributeTable(srcNamespaceID, srcAtom, destNamespaceID, destAtom, element);
 
     rv = ReadNamespace(aStream, srcNamespaceID);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Finally, read in the child nodes.
   uint32_t childCount;
   rv = aStream->Read32(&childCount);
   NS_ENSURE_SUCCESS(rv, rv);
 
   for (uint32_t i = 0; i < childCount; i++) {
     nsCOMPtr<nsIContent> child;
     ReadContentNode(aStream, aDocument, aNim, getter_AddRefs(child));
 
     // Child may be null if this was a comment for example and can just be ignored.
     if (child) {
-      content->AppendChildTo(child, false);
+      element->AppendChildTo(child, false);
     }
   }
 
-  content.swap(*aContent);
+  element.forget(aContent);
   return NS_OK;
 }
 
 nsresult
 nsXBLPrototypeBinding::WriteContentNode(nsIObjectOutputStream* aStream,
                                         nsIContent* aNode)
 {
   nsresult rv;
@@ -1400,40 +1401,41 @@ nsXBLPrototypeBinding::WriteContentNode(
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoString content;
     aNode->GetText()->AppendTo(content);
     return aStream->WriteWStringZ(content.get());
   }
 
   // Otherwise, this is an element.
+  Element* element = aNode->AsElement();
 
   // Write the namespace id followed by the tag name
-  rv = WriteNamespace(aStream, aNode->GetNameSpaceID());
+  rv = WriteNamespace(aStream, element->GetNameSpaceID());
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString prefixStr;
-  aNode->NodeInfo()->GetPrefix(prefixStr);
+  element->NodeInfo()->GetPrefix(prefixStr);
   rv = aStream->WriteWStringZ(prefixStr.get());
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = aStream->WriteWStringZ(nsDependentAtomString(aNode->NodeInfo()->NameAtom()).get());
+  rv = aStream->WriteWStringZ(nsDependentAtomString(element->NodeInfo()->NameAtom()).get());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Write attributes
-  uint32_t count = aNode->GetAttrCount();
+  uint32_t count = element->GetAttrCount();
   rv = aStream->Write32(count);
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t i;
   for (i = 0; i < count; i++) {
     // Write out the namespace id, the namespace prefix, the local tag name,
     // and the value, in that order.
 
-    const BorrowedAttrInfo attrInfo = aNode->GetAttrInfoAt(i);
+    const BorrowedAttrInfo attrInfo = element->GetAttrInfoAt(i);
     const nsAttrName* name = attrInfo.mName;
 
     // XXXndeakin don't write out xbl:inherits?
     int32_t namespaceID = name->NamespaceID();
     rv = WriteNamespace(aStream, namespaceID);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoString prefixStr;
@@ -1457,17 +1459,17 @@ nsXBLPrototypeBinding::WriteContentNode(
     for (auto iter1 = mAttributeTable->Iter(); !iter1.Done(); iter1.Next()) {
       int32_t srcNamespace = iter1.Key();
       InnerAttributeTable* xblAttributes = iter1.UserData();
 
       for (auto iter2 = xblAttributes->Iter(); !iter2.Done(); iter2.Next()) {
         nsXBLAttributeEntry* entry = iter2.UserData();
 
         do {
-          if (entry->GetElement() == aNode) {
+          if (entry->GetElement() == element) {
             WriteNamespace(aStream, srcNamespace);
             aStream->WriteWStringZ(
               nsDependentAtomString(entry->GetSrcAttribute()).get());
             WriteNamespace(aStream, entry->GetDstNameSpace());
             aStream->WriteWStringZ(
               nsDependentAtomString(entry->GetDstAttribute()).get());
           }
 
@@ -1475,22 +1477,22 @@ nsXBLPrototypeBinding::WriteContentNode(
         } while (entry);
       }
     }
   }
   rv = aStream->Write8(XBLBinding_Serialize_NoMoreAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Finally, write out the child nodes.
-  count = aNode->GetChildCount();
+  count = element->GetChildCount();
   rv = aStream->Write32(count);
   NS_ENSURE_SUCCESS(rv, rv);
 
   for (i = 0; i < count; i++) {
-    rv = WriteContentNode(aStream, aNode->GetChildAt(i));
+    rv = WriteContentNode(aStream, element->GetChildAt(i));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 nsresult
 nsXBLPrototypeBinding::ReadNamespace(nsIObjectInputStream* aStream,
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -36,18 +36,18 @@ class nsXBLProtoImplField;
 // by XBLDocumentInfo().  Consumers who want to refcount things should refcount
 // that.
 class nsXBLPrototypeBinding final :
   public mozilla::SupportsWeakPtr<nsXBLPrototypeBinding>
 {
 public:
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsXBLPrototypeBinding)
 
-  nsIContent* GetBindingElement() const { return mBinding; }
-  void SetBindingElement(nsIContent* aElement);
+  mozilla::dom::Element* GetBindingElement() const { return mBinding; }
+  void SetBindingElement(mozilla::dom::Element* aElement);
 
   nsIURI* BindingURI() const { return mBindingURI; }
   nsIURI* AlternateBindingURI() const { return mAlternateBindingURI; }
   nsIURI* DocURI() const { return mXBLDocInfoWeak->DocumentURI(); }
   nsIURI* GetBaseBindingURI() const { return mBaseBindingURI; }
 
   // Checks if aURI refers to this binding by comparing to both possible
   // binding URIs.
@@ -106,26 +106,28 @@ public:
   nsresult ConstructInterfaceTable(const nsAString& aImpls);
 
   void SetImplementation(nsXBLProtoImpl* aImpl) { mImplementation = aImpl; }
   nsXBLProtoImpl* GetImplementation() { return mImplementation; }
   nsresult InstallImplementation(nsXBLBinding* aBinding);
   bool HasImplementation() const { return mImplementation != nullptr; }
 
   void AttributeChanged(nsAtom* aAttribute, int32_t aNameSpaceID,
-                        bool aRemoveFlag, nsIContent* aChangedElement,
+                        bool aRemoveFlag,
+                        mozilla::dom::Element* aChangedElement,
                         nsIContent* aAnonymousContent, bool aNotify);
 
   void SetBasePrototype(nsXBLPrototypeBinding* aBinding);
   nsXBLPrototypeBinding* GetBasePrototype() { return mBaseBinding; }
 
   nsXBLDocumentInfo* XBLDocumentInfo() const { return mXBLDocInfoWeak; }
   bool IsChrome() { return mXBLDocInfoWeak->IsChrome(); }
 
-  void SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent);
+  void SetInitialAttributes(mozilla::dom::Element* aBoundElement,
+                            nsIContent* aAnonymousContent);
 
   void AppendStyleSheet(mozilla::StyleSheet* aSheet);
   void RemoveStyleSheet(mozilla::StyleSheet* aSheet);
   void InsertStyleSheetAt(size_t aIndex, mozilla::StyleSheet* aSheet);
   mozilla::StyleSheet* StyleSheetAt(size_t aIndex) const;
   size_t SheetCount() const;
   bool HasStyleSheets() const;
   void AppendStyleSheetsTo(nsTArray<mozilla::StyleSheet*>& aResult) const;
@@ -241,58 +243,58 @@ public:
   ~nsXBLPrototypeBinding();
 
   // Init must be called after construction to initialize the prototype
   // binding.  It may well throw errors (eg on out-of-memory).  Do not confuse
   // this with the Initialize() method, which must be called after the
   // binding's handlers, properties, etc are all set.
   nsresult Init(const nsACString& aRef,
                 nsXBLDocumentInfo* aInfo,
-                nsIContent* aElement,
+                mozilla::dom::Element* aElement,
                 bool aFirstBinding = false);
 
   void Traverse(nsCycleCollectionTraversalCallback &cb) const;
   void Unlink();
   void Trace(const TraceCallbacks& aCallbacks, void *aClosure) const;
 
 // Internal member functions.
 public:
   /**
    * GetImmediateChild locates the immediate child of our binding element which
    * has the localname given by aTag and is in the XBL namespace.
    */
-  nsIContent* GetImmediateChild(nsAtom* aTag);
-  nsIContent* LocateInstance(nsIContent* aBoundElt,
-                             nsIContent* aTemplRoot,
-                             nsIContent* aCopyRoot,
-                             nsIContent* aTemplChild);
+  mozilla::dom::Element* GetImmediateChild(nsAtom* aTag);
+  mozilla::dom::Element* LocateInstance(mozilla::dom::Element* aBoundElt,
+                                        nsIContent* aTemplRoot,
+                                        nsIContent* aCopyRoot,
+                                        mozilla::dom::Element* aTemplChild);
 
   bool ChromeOnlyContent() { return mChromeOnlyContent; }
   bool BindToUntrustedContent() { return mBindToUntrustedContent; }
 
   typedef nsClassHashtable<nsRefPtrHashKey<nsAtom>, nsXBLAttributeEntry> InnerAttributeTable;
 
 protected:
   // Ensure that mAttributeTable has been created.
   void EnsureAttributeTable();
   // Ad an entry to the attribute table
   void AddToAttributeTable(int32_t aSourceNamespaceID, nsAtom* aSourceTag,
                            int32_t aDestNamespaceID, nsAtom* aDestTag,
-                           nsIContent* aContent);
-  void ConstructAttributeTable(nsIContent* aElement);
+                           mozilla::dom::Element* aContent);
+  void ConstructAttributeTable(mozilla::dom::Element* aElement);
   void CreateKeyHandlers();
 
 private:
   void EnsureResources();
 
 // MEMBER VARIABLES
 protected:
   nsCOMPtr<nsIURI> mBindingURI;
   nsCOMPtr<nsIURI> mAlternateBindingURI; // Alternate id-less URI that is only non-null on the first binding.
-  nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc.
+  RefPtr<mozilla::dom::Element> mBinding; // Strong. We own a ref to our content element in the binding doc.
   nsAutoPtr<nsXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
 
   // the url of the base binding
   nsCOMPtr<nsIURI> mBaseBindingURI;
 
   nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
                                    // the constructor, and the destructor).
 
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -474,89 +474,89 @@ private:
   Element* mElement;
   bool mHadData;
   bool* mResolveStyle;
 };
 
 // This function loads a particular XBL file and installs all of the bindings
 // onto the element.
 nsresult
-nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL,
+nsXBLService::LoadBindings(Element* aElement, nsIURI* aURL,
                            nsIPrincipal* aOriginPrincipal,
                            nsXBLBinding** aBinding, bool* aResolveStyle)
 {
   NS_PRECONDITION(aOriginPrincipal, "Must have an origin principal");
 
   *aBinding = nullptr;
   *aResolveStyle = false;
 
-  AutoEnsureSubtreeStyled subtreeStyled(aContent->AsElement());
+  AutoEnsureSubtreeStyled subtreeStyled(aElement);
 
   if (MOZ_UNLIKELY(!aURL)) {
     return NS_OK;
   }
 
   // Easy case: The binding was already loaded.
-  nsXBLBinding* binding = aContent->GetXBLBinding();
+  nsXBLBinding* binding = aElement->GetXBLBinding();
   if (binding && !binding->MarkedForDeath() &&
       binding->PrototypeBinding()->CompareBindingURI(aURL)) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDocument> document = aContent->OwnerDoc();
+  nsCOMPtr<nsIDocument> document = aElement->OwnerDoc();
 
   nsAutoCString urlspec;
   nsresult rv;
   bool ok = nsContentUtils::GetWrapperSafeScriptFilename(document, aURL,
                                                          urlspec, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (ok) {
     // Block an attempt to load a binding that has special wrapper
     // automation needs.
     return NS_OK;
   }
 
   if (binding) {
-    FlushStyleBindings(aContent);
+    FlushStyleBindings(aElement);
     binding = nullptr;
   }
 
   bool ready;
   RefPtr<nsXBLBinding> newBinding;
-  if (NS_FAILED(rv = GetBinding(aContent, aURL, false, aOriginPrincipal,
+  if (NS_FAILED(rv = GetBinding(aElement, aURL, false, aOriginPrincipal,
                                 &ready, getter_AddRefs(newBinding)))) {
     return rv;
   }
 
   if (!newBinding) {
 #ifdef DEBUG
     nsAutoCString str(NS_LITERAL_CSTRING("Failed to locate XBL binding. XBL is now using id instead of name to reference bindings. Make sure you have switched over.  The invalid binding name is: ") + aURL->GetSpecOrDefault());
     NS_ERROR(str.get());
 #endif
     return NS_OK;
   }
 
-  if (::IsAncestorBinding(document, aURL, aContent)) {
+  if (::IsAncestorBinding(document, aURL, aElement)) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
-  AutoStyleElement styleElement(aContent->AsElement(), aResolveStyle);
+  AutoStyleElement styleElement(aElement, aResolveStyle);
 
   // We loaded a style binding.  It goes on the end.
   // Install the binding on the content node.
-  aContent->SetXBLBinding(newBinding);
+  aElement->SetXBLBinding(newBinding);
 
   {
     nsAutoScriptBlocker scriptBlocker;
 
     // Set the binding's bound element.
-    newBinding->SetBoundElement(aContent);
+    newBinding->SetBoundElement(aElement);
 
     // Tell the binding to build the anonymous content.
     newBinding->GenerateAnonymousContent();
 
     // Tell the binding to install event handlers
     newBinding->InstallEventHandlers();
 
     // Set up our properties
@@ -567,30 +567,28 @@ nsXBLService::LoadBindings(nsIContent* a
     *aResolveStyle = newBinding->HasStyleSheets();
 
     newBinding.forget(aBinding);
   }
 
   return NS_OK;
 }
 
-nsresult
-nsXBLService::FlushStyleBindings(nsIContent* aContent)
+void
+nsXBLService::FlushStyleBindings(Element* aElement)
 {
-  nsCOMPtr<nsIDocument> document = aContent->OwnerDoc();
+  nsCOMPtr<nsIDocument> document = aElement->OwnerDoc();
 
-  nsXBLBinding *binding = aContent->GetXBLBinding();
+  nsXBLBinding* binding = aElement->GetXBLBinding();
   if (binding) {
     // Clear out the script references.
     binding->ChangeDocument(document, nullptr);
 
-    aContent->SetXBLBinding(nullptr); // Flush old style bindings
+    aElement->SetXBLBinding(nullptr); // Flush old style bindings
   }
-
-  return NS_OK;
 }
 
 //
 // AttachGlobalKeyHandler
 //
 // Creates a new key handler and prepares to listen to key events on the given
 // event receiver (either a document or an content node). If the receiver is content,
 // then extra work needs to be done to hook it up to the document (XXX WHY??)
--- a/dom/xbl/nsXBLService.h
+++ b/dom/xbl/nsXBLService.h
@@ -41,17 +41,17 @@ class nsXBLService final : public nsSupp
   }
 
   static nsXBLService* GetInstance() { return gInstance; }
 
   static bool IsChromeOrResourceURI(nsIURI* aURI);
 
   // This function loads a particular XBL file and installs all of the bindings
   // onto the element.  aOriginPrincipal must not be null here.
-  nsresult LoadBindings(nsIContent* aContent, nsIURI* aURL,
+  nsresult LoadBindings(mozilla::dom::Element* aElement, nsIURI* aURL,
                         nsIPrincipal* aOriginPrincipal,
                         nsXBLBinding** aBinding, bool* aResolveStyle);
 
   // Indicates whether or not a binding is fully loaded.
   nsresult BindingReady(nsIContent* aBoundElement, nsIURI* aURI, bool* aIsReady);
 
   // This method checks the hashtable and then calls FetchBindingDocument on a
   // miss.  aOriginPrincipal or aBoundDocument may be null to bypass security
@@ -67,18 +67,18 @@ class nsXBLService final : public nsSupp
   static nsresult AttachGlobalKeyHandler(mozilla::dom::EventTarget* aTarget);
   static nsresult DetachGlobalKeyHandler(mozilla::dom::EventTarget* aTarget);
 
 private:
   nsXBLService();
   virtual ~nsXBLService();
 
 protected:
-  // This function clears out the bindings on a given content node.
-  nsresult FlushStyleBindings(nsIContent* aContent);
+  // This function clears out the bindings on a given element.
+  void FlushStyleBindings(mozilla::dom::Element*);
 
   // This method synchronously loads and parses an XBL file.
   nsresult FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoundDocument,
                                 nsIURI* aDocumentURI, nsIURI* aBindingURI,
                                 nsIPrincipal* aOriginPrincipal, bool aForceSyncLoad,
                                 nsIDocument** aResult);
 
   /**
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -975,17 +975,17 @@ nsXMLContentSink::HandleStartElement(con
   // on the stack inside CreateElement (which is effectively what the HTML sink
   // does), but that's hard with all the subclass overrides going on.
   nsCOMPtr<nsIContent> parent = GetCurrentContent();
 
   result = PushContent(content);
   NS_ENSURE_SUCCESS(result, result);
 
   // Set the attributes on the new content element
-  result = AddAttributes(aAtts, content);
+  result = AddAttributes(aAtts, content->AsElement());
 
   if (NS_OK == result) {
     // Store the element
     if (!SetDocElement(nameSpaceID, localName, content) && appendContent) {
       NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
 
       parent->AppendChildTo(content, false);
     }
@@ -1408,17 +1408,17 @@ nsXMLContentSink::ReportError(const char
 
   FlushTags();
 
   return NS_OK;
 }
 
 nsresult
 nsXMLContentSink::AddAttributes(const char16_t** aAtts,
-                                nsIContent* aContent)
+                                Element* aContent)
 {
   // Add ta