Backout changeset e43f568b3e9a (bug 1423990) because some OSX-only code still doesn't build. r=me
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 25 Dec 2017 12:55:45 +0100
changeset 451704 a8b0e9c18f2f96a8fc0266539d94b2648b246a06
parent 451703 e43f568b3e9a9e7a83bc7d15b28d23dc55960819
child 451705 937ced58fd968217fc931a40757696b31c48299d
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)
reviewersme
bugs1423990
milestone59.0a1
backs oute43f568b3e9a9e7a83bc7d15b28d23dc55960819
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backout changeset e43f568b3e9a (bug 1423990) because some OSX-only code still doesn't build. r=me
accessible/base/ARIAMap.cpp
accessible/base/ARIAStateMap.cpp
accessible/base/AccIterator.cpp
accessible/base/TextAttrs.cpp
accessible/base/nsAccUtils.cpp
accessible/base/nsAccessibilityService.cpp
accessible/base/nsCoreUtils.cpp
accessible/base/nsCoreUtils.h
accessible/base/nsTextEquivUtils.cpp
accessible/generic/ARIAGridAccessible.cpp
accessible/generic/Accessible-inl.h
accessible/generic/Accessible.cpp
accessible/generic/DocAccessible.cpp
accessible/generic/FormControlAccessible.cpp
accessible/generic/HyperTextAccessible.cpp
accessible/generic/ImageAccessible.cpp
accessible/html/HTMLFormControlAccessible.cpp
accessible/html/HTMLImageMapAccessible.cpp
accessible/html/HTMLLinkAccessible.cpp
accessible/html/HTMLSelectAccessible.cpp
accessible/html/HTMLTableAccessible.cpp
accessible/windows/msaa/AccessibleWrap.cpp
accessible/windows/msaa/XULMenuAccessibleWrap.cpp
accessible/xul/XULColorPickerAccessible.cpp
accessible/xul/XULComboboxAccessible.cpp
accessible/xul/XULElementAccessibles.cpp
accessible/xul/XULFormControlAccessible.cpp
accessible/xul/XULListboxAccessible.cpp
accessible/xul/XULMenuAccessible.cpp
accessible/xul/XULSliderAccessible.cpp
accessible/xul/XULTabAccessible.cpp
accessible/xul/XULTreeGridAccessible.cpp
docshell/base/nsDocShell.cpp
dom/base/Element.h
dom/base/FragmentOrElement.cpp
dom/base/ShadowRoot.cpp
dom/base/nsContentList.cpp
dom/base/nsContentSink.cpp
dom/base/nsContentUtils.cpp
dom/base/nsDocument.cpp
dom/base/nsFocusManager.cpp
dom/base/nsFocusManager.h
dom/base/nsIContent.h
dom/base/nsObjectLoadingContent.cpp
dom/base/nsStyleLinkElement.cpp
dom/base/nsTextNode.cpp
dom/base/nsXHTMLContentSerializer.cpp
dom/base/nsXMLContentSerializer.cpp
dom/events/ContentEventHandler.cpp
dom/events/EventStateManager.cpp
dom/events/EventStateManager.h
dom/events/IMEStateManager.cpp
dom/html/HTMLFormElement.cpp
dom/html/HTMLFormElement.h
dom/html/HTMLFormSubmission.cpp
dom/html/HTMLFormSubmission.h
dom/html/HTMLImageElement.cpp
dom/html/HTMLImageElement.h
dom/html/HTMLInputElement.cpp
dom/html/HTMLLinkElement.cpp
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/html/HTMLMenuElement.cpp
dom/html/HTMLSharedElement.cpp
dom/html/HTMLTableElement.cpp
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/html/nsIConstraintValidation.cpp
dom/html/nsTextEditorState.cpp
dom/mathml/nsMathMLElement.cpp
dom/script/ScriptLoader.cpp
dom/svg/SVGAElement.cpp
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xbl/nsXBLPrototypeHandler.cpp
dom/xbl/nsXBLPrototypeHandler.h
dom/xbl/nsXBLWindowKeyHandler.cpp
dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
dom/xslt/xslt/txMozillaXMLOutput.cpp
dom/xul/XULDocument.cpp
dom/xul/XULDocument.h
dom/xul/nsXULElement.cpp
dom/xul/nsXULPopupListener.cpp
dom/xul/nsXULPopupListener.h
dom/xul/templates/nsXULContentBuilder.cpp
dom/xul/templates/nsXULContentUtils.cpp
dom/xul/templates/nsXULContentUtils.h
dom/xul/templates/nsXULSortService.cpp
dom/xul/templates/nsXULTemplateBuilder.cpp
dom/xul/templates/nsXULTemplateBuilder.h
dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
dom/xul/templates/nsXULTemplateQueryProcessorRDF.h
dom/xul/templates/nsXULTemplateQueryProcessorStorage.cpp
dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp
dom/xul/templates/nsXULTreeBuilder.cpp
dom/xul/templates/nsXULTreeBuilder.h
editor/composer/nsComposeTxtSrvFilter.cpp
editor/libeditor/HTMLStyleEditor.cpp
editor/libeditor/TextEditor.cpp
extensions/spellcheck/src/mozInlineSpellChecker.cpp
layout/base/PositionedEventTargeting.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/forms/nsCheckboxRadioFrame.cpp
layout/forms/nsDateTimeControlFrame.cpp
layout/forms/nsFileControlFrame.cpp
layout/forms/nsGfxButtonControlFrame.cpp
layout/forms/nsImageControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/forms/nsNumberControlFrame.cpp
layout/forms/nsTextControlFrame.cpp
layout/forms/nsTextControlFrame.h
layout/generic/BlockReflowInput.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsImageMap.cpp
layout/generic/nsPluginFrame.cpp
layout/generic/nsTextFrame.cpp
layout/mathml/nsMathMLmactionFrame.cpp
layout/mathml/nsMathMLmencloseFrame.cpp
layout/mathml/nsMathMLmfencedFrame.cpp
layout/mathml/nsMathMLmfracFrame.cpp
layout/mathml/nsMathMLmmultiscriptsFrame.cpp
layout/mathml/nsMathMLmoFrame.cpp
layout/mathml/nsMathMLmpaddedFrame.cpp
layout/mathml/nsMathMLmspaceFrame.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/mathml/nsMathMLmunderoverFrame.cpp
layout/mathml/nsMathMLsemanticsFrame.cpp
layout/style/nsStyleUtil.cpp
layout/style/nsStyleUtil.h
layout/svg/SVGViewFrame.cpp
layout/tables/BasicTableLayoutStrategy.cpp
layout/xul/nsBox.cpp
layout/xul/nsBoxFrame.cpp
layout/xul/nsButtonBoxFrame.cpp
layout/xul/nsDeckFrame.cpp
layout/xul/nsImageBoxFrame.cpp
layout/xul/nsLeafBoxFrame.cpp
layout/xul/nsListBoxBodyFrame.cpp
layout/xul/nsListItemFrame.cpp
layout/xul/nsMenuBarFrame.cpp
layout/xul/nsMenuFrame.cpp
layout/xul/nsMenuPopupFrame.cpp
layout/xul/nsProgressMeterFrame.cpp
layout/xul/nsResizerFrame.cpp
layout/xul/nsScrollBoxFrame.cpp
layout/xul/nsScrollbarButtonFrame.cpp
layout/xul/nsSliderFrame.cpp
layout/xul/nsSplitterFrame.cpp
layout/xul/nsStackLayout.cpp
layout/xul/nsTextBoxFrame.cpp
layout/xul/nsTitleBarFrame.cpp
layout/xul/nsXULLabelFrame.cpp
layout/xul/nsXULPopupManager.cpp
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/nsTreeSelection.cpp
parser/html/nsHtml5TreeOperation.cpp
toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
widget/cocoa/nsMenuBarX.mm
widget/cocoa/nsMenuItemIconX.mm
widget/cocoa/nsMenuItemX.mm
widget/cocoa/nsMenuUtilsX.mm
widget/cocoa/nsMenuX.mm
widget/cocoa/nsNativeThemeCocoa.mm
widget/gtk/nsNativeThemeGTK.cpp
widget/nsNativeTheme.cpp
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -1370,20 +1370,18 @@ aria::AttrCharacteristicsFor(nsAtom* aAt
   return 0;
 }
 
 bool
 aria::HasDefinedARIAHidden(nsIContent* aContent)
 {
   return aContent &&
     nsAccUtils::HasDefinedARIAToken(aContent, nsGkAtoms::aria_hidden) &&
-    !aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                        nsGkAtoms::aria_hidden,
-                                        nsGkAtoms::_false,
-                                        eCaseMatters);
+    !aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_hidden,
+                           nsGkAtoms::_false, eCaseMatters);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AttrIterator class
 
 bool
 AttrIterator::Next(nsAString& aAttrName, nsAString& aAttrValue)
 {
--- a/accessible/base/ARIAStateMap.cpp
+++ b/accessible/base/ARIAStateMap.cpp
@@ -18,17 +18,17 @@ using namespace mozilla::a11y::aria;
  * Used to store state map rule data for ARIA attribute of enum type.
  */
 struct EnumTypeData
 {
   // ARIA attribute name.
   nsStaticAtom* const mAttrName;
 
   // States if the attribute value is matched to the enum value. Used as
-  // Element::AttrValuesArray, last item must be nullptr.
+  // nsIContent::AttrValuesArray, last item must be nullptr.
   nsStaticAtom* const* const mValues[4];
 
   // States applied if corresponding enum values are matched.
   const uint64_t mStates[3];
 
   // States to clear in case of match.
   const uint64_t mClearState;
 };
--- a/accessible/base/AccIterator.cpp
+++ b/accessible/base/AccIterator.cpp
@@ -80,18 +80,17 @@ RelatedAccIterator::
   mDocument(aDocument), mRelAttr(aRelAttr), mProviders(nullptr),
   mBindingParent(nullptr), mIndex(0)
 {
   mBindingParent = aDependentContent->GetBindingParent();
   nsAtom* IDAttr = mBindingParent ?
     nsGkAtoms::anonid : nsGkAtoms::id;
 
   nsAutoString id;
-  if (aDependentContent->IsElement() &&
-      aDependentContent->AsElement()->GetAttr(kNameSpaceID_None, IDAttr, id))
+  if (aDependentContent->GetAttr(kNameSpaceID_None, IDAttr, id))
     mProviders = mDocument->mDependentIDsHash.Get(id);
 }
 
 Accessible*
 RelatedAccIterator::Next()
 {
   if (!mProviders)
     return nullptr;
@@ -161,17 +160,17 @@ HTMLLabelIterator::Next()
 
   // Go up tree to get a name of ancestor label if there is one (an ancestor
   // <label> implicitly points to us). Don't go up farther than form or
   // document.
   Accessible* walkUp = mAcc->Parent();
   while (walkUp && !walkUp->IsDoc()) {
     nsIContent* walkUpEl = walkUp->GetContent();
     if (IsLabel(walkUp) &&
-        !walkUpEl->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::_for)) {
+        !walkUpEl->HasAttr(kNameSpaceID_None, nsGkAtoms::_for)) {
       mLabelFilter = eSkipAncestorLabel; // prevent infinite loop
       return walkUp;
     }
 
     if (walkUpEl->IsHTMLElement(nsGkAtoms::form))
       break;
 
     walkUp = walkUp->Parent();
@@ -253,18 +252,18 @@ XULDescriptionIterator::Next()
 // IDRefsIterator
 ////////////////////////////////////////////////////////////////////////////////
 
 IDRefsIterator::
   IDRefsIterator(DocAccessible* aDoc, nsIContent* aContent,
                  nsAtom* aIDRefsAttr) :
   mContent(aContent), mDoc(aDoc), mCurrIdx(0)
 {
-  if (mContent->IsInUncomposedDoc() && mContent->IsElement())
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs);
+  if (mContent->IsInUncomposedDoc())
+    mContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs);
 }
 
 const nsDependentSubstring
 IDRefsIterator::NextID()
 {
   for (; mCurrIdx < mIDs.Length(); mCurrIdx++) {
     if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
       break;
--- a/accessible/base/TextAttrs.cpp
+++ b/accessible/base/TextAttrs.cpp
@@ -296,23 +296,23 @@ TextAttrsMgr::InvalidTextAttr::
 
 bool
 TextAttrsMgr::InvalidTextAttr::
   GetValue(nsIContent* aElm, uint32_t* aValue)
 {
   nsIContent* elm = aElm;
   do {
     if (nsAccUtils::HasDefinedARIAToken(elm, nsGkAtoms::aria_invalid)) {
-      static Element::AttrValuesArray tokens[] =
+      static nsIContent::AttrValuesArray tokens[] =
         { &nsGkAtoms::_false, &nsGkAtoms::grammar, &nsGkAtoms::spelling,
           nullptr };
 
-      int32_t idx = elm->AsElement()->FindAttrValueIn(kNameSpaceID_None,
-                                                      nsGkAtoms::aria_invalid,
-                                                      tokens, eCaseMatters);
+      int32_t idx = elm->FindAttrValueIn(kNameSpaceID_None,
+                                         nsGkAtoms::aria_invalid, tokens,
+                                         eCaseMatters);
       switch (idx) {
         case 0:
           *aValue = eFalse;
           return true;
         case 1:
           *aValue = eGrammar;
           return true;
         case 2:
--- a/accessible/base/nsAccUtils.cpp
+++ b/accessible/base/nsAccUtils.cpp
@@ -136,90 +136,83 @@ nsAccUtils::SetLiveContainerAttributes(n
 {
   nsAutoString live, relevant, busy;
   nsIContent* ancestor = aStartContent;
   while (ancestor) {
 
     // container-relevant attribute
     if (relevant.IsEmpty() &&
         HasDefinedARIAToken(ancestor, nsGkAtoms::aria_relevant) &&
-        ancestor->AsElement()->GetAttr(kNameSpaceID_None,
-                                       nsGkAtoms::aria_relevant, relevant))
+        ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_relevant, relevant))
       SetAccAttr(aAttributes, nsGkAtoms::containerRelevant, relevant);
 
     // container-live, and container-live-role attributes
     if (live.IsEmpty()) {
       const nsRoleMapEntry* role = nullptr;
       if (ancestor->IsElement()) {
         role = aria::GetRoleMap(ancestor->AsElement());
       }
       if (HasDefinedARIAToken(ancestor, nsGkAtoms::aria_live)) {
-        ancestor->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_live, live);
+        ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_live, live);
       } else if (role) {
         GetLiveAttrValue(role->liveAttRule, live);
       }
       if (!live.IsEmpty()) {
         SetAccAttr(aAttributes, nsGkAtoms::containerLive, live);
         if (role) {
           SetAccAttr(aAttributes, nsGkAtoms::containerLiveRole,
                      role->ARIARoleString());
         }
       }
     }
 
     // container-atomic attribute
-    if (ancestor->IsElement() &&
-        ancestor->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::aria_atomic,
-                                           nsGkAtoms::_true, eCaseMatters)) {
+    if (ancestor->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_atomic,
+                              nsGkAtoms::_true, eCaseMatters)) {
       SetAccAttr(aAttributes, nsGkAtoms::containerAtomic,
                  NS_LITERAL_STRING("true"));
     }
 
     // container-busy attribute
     if (busy.IsEmpty() &&
         HasDefinedARIAToken(ancestor, nsGkAtoms::aria_busy) &&
-        ancestor->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_busy, busy))
+        ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_busy, busy))
       SetAccAttr(aAttributes, nsGkAtoms::containerBusy, busy);
 
     if (ancestor == aTopEl)
       break;
 
     ancestor = ancestor->GetParent();
     if (!ancestor)
       ancestor = aTopEl; // Use <body>/<frameset>
   }
 }
 
 bool
 nsAccUtils::HasDefinedARIAToken(nsIContent *aContent, nsAtom *aAtom)
 {
   NS_ASSERTION(aContent, "aContent is null in call to HasDefinedARIAToken!");
 
-  if (!aContent->IsElement())
-    return false;
-
-  Element* element = aContent->AsElement();
-  if (!element->HasAttr(kNameSpaceID_None, aAtom) ||
-      element->AttrValueIs(kNameSpaceID_None, aAtom, nsGkAtoms::_empty,
-                           eCaseMatters) ||
-      element->AttrValueIs(kNameSpaceID_None, aAtom, nsGkAtoms::_undefined,
-                           eCaseMatters)) {
+  if (!aContent->HasAttr(kNameSpaceID_None, aAtom) ||
+      aContent->AttrValueIs(kNameSpaceID_None, aAtom,
+                            nsGkAtoms::_empty, eCaseMatters) ||
+      aContent->AttrValueIs(kNameSpaceID_None, aAtom,
+                            nsGkAtoms::_undefined, eCaseMatters)) {
         return false;
   }
   return true;
 }
 
 nsAtom*
 nsAccUtils::GetARIAToken(dom::Element* aElement, nsAtom* aAttr)
 {
   if (!HasDefinedARIAToken(aElement, aAttr))
     return nsGkAtoms::_empty;
 
-  static Element::AttrValuesArray tokens[] =
+  static nsIContent::AttrValuesArray tokens[] =
     { &nsGkAtoms::_false, &nsGkAtoms::_true,
       &nsGkAtoms::mixed, nullptr};
 
   int32_t idx = aElement->FindAttrValueIn(kNameSpaceID_None,
                                           aAttr, tokens, eCaseMatters);
   if (idx >= 0)
     return *(tokens[idx]);
 
@@ -241,19 +234,17 @@ nsAccUtils::GetSelectableContainer(Acces
       return nullptr;
   }
   return parent;
 }
 
 bool
 nsAccUtils::IsARIASelected(Accessible* aAccessible)
 {
-  if (!aAccessible->GetContent()->IsElement())
-    return false;
-  return aAccessible->GetContent()->AsElement()->
+  return aAccessible->GetContent()->
     AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_selected,
                 nsGkAtoms::_true, eCaseMatters);
 }
 
 Accessible*
 nsAccUtils::TableFor(Accessible* aRow)
 {
   if (aRow) {
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -204,35 +204,30 @@ New_HTMLDefinition(nsIContent* aContent,
   return nullptr;
 }
 
 static Accessible* New_HTMLLabel(nsIContent* aContent, Accessible* aContext)
   { return new HTMLLabelAccessible(aContent, aContext->Document()); }
 
 static Accessible* New_HTMLInput(nsIContent* aContent, Accessible* aContext)
 {
-  if (!aContent->IsElement()) {
-    return nullptr;
-  }
-
-  Element* element = aContent->AsElement();
-  if (element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                           nsGkAtoms::checkbox, eIgnoreCase)) {
+  if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::checkbox, eIgnoreCase)) {
     return new HTMLCheckboxAccessible(aContent, aContext->Document());
   }
-  if (element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                           nsGkAtoms::radio, eIgnoreCase)) {
+  if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::radio, eIgnoreCase)) {
     return new HTMLRadioButtonAccessible(aContent, aContext->Document());
   }
-  if (element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                           nsGkAtoms::time, eIgnoreCase)) {
+  if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::time, eIgnoreCase)) {
     return new EnumRoleAccessible<roles::GROUPING>(aContent, aContext->Document());
   }
-  if (element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                           nsGkAtoms::date, eIgnoreCase)) {
+  if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::date, eIgnoreCase)) {
     return new EnumRoleAccessible<roles::DATE_EDITOR>(aContent, aContext->Document());
   }
   return nullptr;
 }
 
 static Accessible* New_HTMLOutput(nsIContent* aContent, Accessible* aContext)
   { return new HTMLOutputAccessible(aContent, aContext->Document()); }
 
@@ -261,35 +256,32 @@ New_HTMLTableHeaderCell(nsIContent* aCon
     return new HTMLTableHeaderCellAccessibleWrap(aContent, aContext->Document());
   return nullptr;
 }
 
 static Accessible*
 New_HTMLTableHeaderCellIfScope(nsIContent* aContent, Accessible* aContext)
 {
   if (aContext->IsTableRow() && aContext->GetContent() == aContent->GetParent() &&
-      aContent->IsElement() &&
-      aContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::scope))
+      aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope))
     return new HTMLTableHeaderCellAccessibleWrap(aContent, aContext->Document());
   return nullptr;
 }
 
 #ifdef MOZ_XUL
 static Accessible*
 New_MaybeImageOrToolbarButtonAccessible(nsIContent* aContent,
                                         Accessible* aContext)
 {
-  if (aContent->IsElement() &&
-      aContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::onclick)) {
+  if (aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::onclick)) {
     return new XULToolbarButtonAccessible(aContent, aContext->Document());
   }
 
   // Don't include nameless images in accessible tree.
-  if (!aContent->IsElement() ||
-      !aContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext)) {
+  if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext)) {
     return nullptr;
   }
 
   return new ImageAccessibleWrap(aContent, aContext->Document());
 }
 static Accessible*
 New_MenuSeparator(nsIContent* aContent, Accessible* aContext)
   { return new XULMenuSeparatorAccessible(aContent, aContext->Document()); }
@@ -1554,20 +1546,18 @@ nsAccessibilityService::CreateAccessible
 #endif
 
     accessible = new XULMenupopupAccessible(aContent, aDoc);
 
   } else if(role.EqualsLiteral("xul:pane")) {
     accessible = new EnumRoleAccessible<roles::PANE>(aContent, aDoc);
 
   } else if (role.EqualsLiteral("xul:panel")) {
-    if (aContent->IsElement() &&
-        aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::noautofocus,
-                                           nsGkAtoms::_true, eCaseMatters))
+    if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautofocus,
+                              nsGkAtoms::_true, eCaseMatters))
       accessible = new XULAlertAccessible(aContent, aDoc);
     else
       accessible = new EnumRoleAccessible<roles::PANE>(aContent, aDoc);
 
   } else if (role.EqualsLiteral("xul:progressmeter")) {
     accessible = new XULProgressMeterAccessible(aContent, aDoc);
 
   } else if (role.EqualsLiteral("xul:scale")) {
@@ -1770,32 +1760,25 @@ nsAccessibilityService::MarkupAttributes
 
   for (uint32_t i = 0; i < ArrayLength(markupMap->attrs); i++) {
     const MarkupAttrInfo* info = markupMap->attrs + i;
     if (!info->name)
       break;
 
     if (info->DOMAttrName) {
       if (info->DOMAttrValue) {
-        if (aContent->IsElement() &&
-            aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                               *info->DOMAttrName,
-                                               *info->DOMAttrValue,
-                                               eCaseMatters)) {
+        if (aContent->AttrValueIs(kNameSpaceID_None, *info->DOMAttrName,
+                                  *info->DOMAttrValue, eCaseMatters)) {
           nsAccUtils::SetAccAttr(aAttributes, *info->name, *info->DOMAttrValue);
         }
         continue;
       }
 
       nsAutoString value;
-
-      if (aContent->IsElement()) {
-        aContent->AsElement()->GetAttr(kNameSpaceID_None, *info->DOMAttrName, value);
-      }
-
+      aContent->GetAttr(kNameSpaceID_None, *info->DOMAttrName, value);
       if (!value.IsEmpty())
         nsAccUtils::SetAccAttr(aAttributes, *info->name, value);
 
       continue;
     }
 
     nsAccUtils::SetAccAttr(aAttributes, *info->name, *info->value);
   }
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -179,33 +179,32 @@ nsCoreUtils::DispatchTouchEvent(EventMes
 }
 
 uint32_t
 nsCoreUtils::GetAccessKeyFor(nsIContent* aContent)
 {
   // Accesskeys are registered by @accesskey attribute only. At first check
   // whether it is presented on the given element to avoid the slow
   // EventStateManager::GetRegisteredAccessKey() method.
-  if (!aContent->IsElement() ||
-      !aContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::accesskey))
+  if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::accesskey))
     return 0;
 
   nsIPresShell* presShell = aContent->OwnerDoc()->GetShell();
   if (!presShell)
     return 0;
 
   nsPresContext *presContext = presShell->GetPresContext();
   if (!presContext)
     return 0;
 
   EventStateManager *esm = presContext->EventStateManager();
   if (!esm)
     return 0;
 
-  return esm->GetRegisteredAccessKey(aContent->AsElement());
+  return esm->GetRegisteredAccessKey(aContent);
 }
 
 nsIContent *
 nsCoreUtils::GetDOMElementFor(nsIContent *aContent)
 {
   if (aContent->IsElement())
     return aContent;
 
@@ -451,28 +450,24 @@ nsCoreUtils::IsErrorPage(nsIDocument *aD
   NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
 
   return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
 }
 
 bool
 nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID)
 {
-  return aContent->IsElement() &&
-    aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aID);
+  return aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aID);
 }
 
 bool
 nsCoreUtils::GetUIntAttr(nsIContent *aContent, nsAtom *aAttr, int32_t *aUInt)
 {
   nsAutoString value;
-  if (!aContent->IsElement()) {
-    return false;
-  }
-  aContent->AsElement()->GetAttr(kNameSpaceID_None, aAttr, value);
+  aContent->GetAttr(kNameSpaceID_None, aAttr, value);
   if (!value.IsEmpty()) {
     nsresult error = NS_OK;
     int32_t integer = value.ToInteger(&error);
     if (NS_SUCCEEDED(error) && integer > 0) {
       *aUInt = integer;
       return true;
     }
   }
@@ -483,18 +478,17 @@ nsCoreUtils::GetUIntAttr(nsIContent *aCo
 void
 nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
                             nsAString& aLanguage)
 {
   aLanguage.Truncate();
 
   nsIContent *walkUp = aContent;
   while (walkUp && walkUp != aRootContent &&
-         (!walkUp->IsElement() ||
-          !walkUp->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLanguage)))
+         !walkUp->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLanguage))
     walkUp = walkUp->GetParent();
 }
 
 already_AddRefed<nsIBoxObject>
 nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
 {
   nsCOMPtr<nsIDOMElement> tcElm;
   aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
@@ -618,17 +612,17 @@ nsCoreUtils::GetPreviousSensibleColumn(n
   return prevColumn.forget();
 }
 
 bool
 nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
 {
   nsCOMPtr<nsIDOMElement> element;
   aColumn->GetElement(getter_AddRefs(element));
-  nsCOMPtr<Element> content = do_QueryInterface(element);
+  nsCOMPtr<nsIContent> content = do_QueryInterface(element);
   return content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
                               nsGkAtoms::_true, eCaseMatters);
 }
 
 void
 nsCoreUtils::ScrollTo(nsIPresShell* aPresShell, nsIContent* aContent,
                       uint32_t aScrollType)
 {
@@ -678,14 +672,14 @@ nsCoreUtils::DispatchAccEvent(RefPtr<nsI
   obsService->NotifyObservers(event, NS_ACCESSIBLE_EVENT_TOPIC, nullptr);
 }
 
 void
 nsCoreUtils::XBLBindingRole(const nsIContent* aEl, nsAString& aRole)
 {
   for (const nsXBLBinding* binding = aEl->GetXBLBinding(); binding;
        binding = binding->GetBaseBinding()) {
-    Element* bindingElm = binding->PrototypeBinding()->GetBindingElement();
+    nsIContent* bindingElm = binding->PrototypeBinding()->GetBindingElement();
     bindingElm->GetAttr(kNameSpaceID_None, nsGkAtoms::role, aRole);
     if (!aRole.IsEmpty())
       break;
   }
 }
--- a/accessible/base/nsCoreUtils.h
+++ b/accessible/base/nsCoreUtils.h
@@ -2,17 +2,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/. */
 
 #ifndef nsCoreUtils_h_
 #define nsCoreUtils_h_
 
 #include "mozilla/EventForwards.h"
-#include "mozilla/dom/Element.h"
 #include "nsIAccessibleEvent.h"
 #include "nsIContent.h"
 #include "nsIDocument.h" // for GetShell()
 #include "nsIPresShell.h"
 
 #include "nsPoint.h"
 #include "nsTArray.h"
 
@@ -287,18 +286,17 @@ public:
                        uint32_t aScrollType);
 
   /**
    * Return true if the given node is table header element.
    */
   static bool IsHTMLTableHeader(nsIContent *aContent)
   {
     return aContent->NodeInfo()->Equals(nsGkAtoms::th) ||
-      (aContent->IsElement() &&
-       aContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::scope));
+      aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope);
   }
 
   /**
    * Returns true if the given string is empty or contains whitespace symbols
    * only. In contrast to nsWhitespaceTokenizer class it takes into account
    * non-breaking space (0xa0).
    */
   static bool IsWhitespaceString(const nsAString& aString);
--- a/accessible/base/nsTextEquivUtils.cpp
+++ b/accessible/base/nsTextEquivUtils.cpp
@@ -308,22 +308,22 @@ nsTextEquivUtils::AppendFromDOMNode(nsIC
     nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl =
       do_QueryInterface(aContent);
 
     if (labeledEl) {
       labeledEl->GetLabel(textEquivalent);
     } else {
       if (aContent->NodeInfo()->Equals(nsGkAtoms::label,
                                        kNameSpaceID_XUL))
-        aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value,
-                                       textEquivalent);
+        aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value,
+                          textEquivalent);
 
       if (textEquivalent.IsEmpty())
-        aContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                       nsGkAtoms::tooltiptext, textEquivalent);
+        aContent->GetAttr(kNameSpaceID_None,
+                          nsGkAtoms::tooltiptext, textEquivalent);
     }
 
     AppendString(aString, textEquivalent);
   }
 
   return AppendFromDOMChildren(aContent, aString);
 }
 
--- a/accessible/generic/ARIAGridAccessible.cpp
+++ b/accessible/generic/ARIAGridAccessible.cpp
@@ -636,20 +636,21 @@ ARIAGridCellAccessible::ApplyARIAState(u
     return;
 
   // Check aria-selected="true" on the row.
   Accessible* row = Parent();
   if (!row || row->Role() != roles::ROW)
     return;
 
   nsIContent *rowContent = row->GetContent();
-  if (nsAccUtils::HasDefinedARIAToken(rowContent, nsGkAtoms::aria_selected) &&
-      !rowContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                            nsGkAtoms::aria_selected,
-                                            nsGkAtoms::_false, eCaseMatters))
+  if (nsAccUtils::HasDefinedARIAToken(rowContent,
+                                      nsGkAtoms::aria_selected) &&
+      !rowContent->AttrValueIs(kNameSpaceID_None,
+                               nsGkAtoms::aria_selected,
+                               nsGkAtoms::_false, eCaseMatters))
     *aState |= states::SELECTABLE | states::SELECTED;
 }
 
 already_AddRefed<nsIPersistentProperties>
 ARIAGridCellAccessible::NativeAttributes()
 {
   nsCOMPtr<nsIPersistentProperties> attributes =
     HyperTextAccessibleWrap::NativeAttributes();
--- a/accessible/generic/Accessible-inl.h
+++ b/accessible/generic/Accessible-inl.h
@@ -71,18 +71,18 @@ Accessible::SetRoleMapEntry(const nsRole
 }
 
 inline bool
 Accessible::IsSearchbox() const
 {
   const nsRoleMapEntry* roleMapEntry = ARIARoleMap();
   return (roleMapEntry && roleMapEntry->Is(nsGkAtoms::searchbox)) ||
     (mContent->IsHTMLElement(nsGkAtoms::input) &&
-     mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                        nsGkAtoms::search, eCaseMatters));
+     mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                           nsGkAtoms::search, eCaseMatters));
 }
 
 inline bool
 Accessible::HasGenericType(AccGenericType aType) const
 {
   const nsRoleMapEntry* roleMapEntry = ARIARoleMap();
   return (mGenericTypes & aType) ||
     (roleMapEntry && roleMapEntry->IsOfType(aType));
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -148,22 +148,22 @@ Accessible::Name(nsString& aName)
   }
 
   ENameValueFlag nameFlag = NativeName(aName);
   if (!aName.IsEmpty())
     return nameFlag;
 
   // In the end get the name from tooltip.
   if (mContent->IsHTMLElement()) {
-    if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName)) {
+    if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName)) {
       aName.CompressWhitespace();
       return eNameFromTooltip;
     }
   } else if (mContent->IsXULElement()) {
-    if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aName)) {
+    if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aName)) {
       aName.CompressWhitespace();
       return eNameFromTooltip;
     }
   } else if (mContent->IsSVGElement()) {
     // If user agents need to choose among multiple ‘desc’ or ‘title’ elements
     // for processing, the user agent shall choose the first one.
     for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
          childElm = childElm->GetNextSibling()) {
@@ -197,19 +197,19 @@ Accessible::Description(nsString& aDescr
                            aDescription);
 
   if (aDescription.IsEmpty()) {
     NativeDescription(aDescription);
 
     if (aDescription.IsEmpty()) {
       // Keep the Name() method logic.
       if (mContent->IsHTMLElement()) {
-        mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aDescription);
+        mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aDescription);
       } else if (mContent->IsXULElement()) {
-        mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aDescription);
+        mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aDescription);
       } else if (mContent->IsSVGElement()) {
         for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
              childElm = childElm->GetNextSibling()) {
           if (childElm->IsSVGElement(nsGkAtoms::desc)) {
             nsTextEquivUtils::AppendTextEquivFromContent(this, childElm,
                                                          &aDescription);
             break;
           }
@@ -446,17 +446,17 @@ Accessible::NativeState()
         else
           state |= states::HORIZONTAL;
       }
     }
   }
 
   // Check if a XUL element has the popup attribute (an attached popup menu).
   if (HasOwnContent() && mContent->IsXULElement() &&
-      mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::popup))
+      mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::popup))
     state |= states::HASPOPUP;
 
   // Bypass the link states specialization for non links.
   const nsRoleMapEntry* roleMapEntry = ARIARoleMap();
   if (!roleMapEntry || roleMapEntry->roleRule == kUseNativeRole ||
       roleMapEntry->role == roles::LINK)
     state |= NativeLinkState();
 
@@ -486,19 +486,18 @@ Accessible::NativeLinkState() const
 }
 
 bool
 Accessible::NativelyUnavailable() const
 {
   if (mContent->IsHTMLElement())
     return mContent->AsElement()->State().HasState(NS_EVENT_STATE_DISABLED);
 
-  return mContent->IsElement() &&
-    mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
-                                       nsGkAtoms::_true, eCaseMatters);
+  return mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
+                               nsGkAtoms::_true, eCaseMatters);
 }
 
 Accessible*
 Accessible::FocusedChild()
 {
   Accessible* focus = FocusMgr()->FocusedAccessible();
   if (focus && (focus == this || focus->Parent() == this))
     return focus;
@@ -823,20 +822,19 @@ Accessible::XULElmName(DocAccessible* aD
 
   // Can get text from title of <toolbaritem> if we're a child of a <toolbaritem>
   nsIContent *bindingParent = aElm->GetBindingParent();
   nsIContent* parent =
     bindingParent? bindingParent->GetParent() : aElm->GetParent();
   nsAutoString ancestorTitle;
   while (parent) {
     if (parent->IsXULElement(nsGkAtoms::toolbaritem) &&
-        parent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::title, ancestorTitle)) {
+        parent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, ancestorTitle)) {
       // Before returning this, check if the element itself has a tooltip:
-      if (aElm->IsElement() &&
-          aElm->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aName)) {
+      if (aElm->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aName)) {
         aName.CompressWhitespace();
         return;
       }
 
       aName.Assign(ancestorTitle);
       aName.CompressWhitespace();
       return;
     }
@@ -941,17 +939,17 @@ Accessible::Attributes()
   // 'xml-roles' attribute for landmark.
   nsAtom* landmark = LandmarkRole();
   if (landmark) {
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles, landmark);
 
   } else {
     // 'xml-roles' attribute coming from ARIA.
     nsAutoString xmlRoles;
-    if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::role, xmlRoles))
+    if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::role, xmlRoles))
       nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles, xmlRoles);
   }
 
   // Expose object attributes from ARIA attributes.
   nsAutoString unused;
   aria::AttrIterator attribIter(mContent);
   nsAutoString name, value;
   while(attribIter.Next(name, value))
@@ -1062,17 +1060,17 @@ Accessible::NativeAttributes()
     return attributes.forget();
 
   nsAutoString id;
   if (nsCoreUtils::GetID(mContent, id))
     attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, unused);
 
   // Expose class because it may have useful microformat information.
   nsAutoString _class;
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, _class))
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, _class))
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::_class, _class);
 
   // Expose tag.
   nsAutoString tagName;
   mContent->NodeInfo()->GetName(tagName);
   nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tag, tagName);
 
   // Expose draggable object attribute.
@@ -1176,20 +1174,19 @@ Accessible::State()
   // Apply ARIA states to be sure accessible states will be overridden.
   ApplyARIAState(&state);
 
   // If this is an ARIA item of the selectable widget and if it's focused and
   // not marked unselected explicitly (i.e. aria-selected="false") then expose
   // it as selected to make ARIA widget authors life easier.
   const nsRoleMapEntry* roleMapEntry = ARIARoleMap();
   if (roleMapEntry && !(state & states::SELECTED) &&
-      (!mContent->IsElement() ||
-       !mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::aria_selected,
-                                           nsGkAtoms::_false, eCaseMatters))) {
+      !mContent->AttrValueIs(kNameSpaceID_None,
+                             nsGkAtoms::aria_selected,
+                             nsGkAtoms::_false, eCaseMatters)) {
     // Special case for tabs: focused tab or focus inside related tab panel
     // implies selected state.
     if (roleMapEntry->role == roles::PAGETAB) {
       if (state & states::FOCUSED) {
         state |= states::SELECTED;
       } else {
         // If focus is in a child of the tab panel surely the tab is selected!
         Relation rel = RelationByType(RelationType::LABEL_FOR);
@@ -1337,24 +1334,20 @@ Accessible::Value(nsString& aValue)
   const nsRoleMapEntry* roleMapEntry = ARIARoleMap();
   if (!roleMapEntry)
     return;
 
   if (roleMapEntry->valueRule != eNoValue) {
     // aria-valuenow is a number, and aria-valuetext is the optional text
     // equivalent. For the string value, we will try the optional text
     // equivalent first.
-    if (!mContent->IsElement()) {
-      return;
-    }
-
-    if (!mContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                        nsGkAtoms::aria_valuetext, aValue)) {
-      mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow,
-                                     aValue);
+    if (!mContent->GetAttr(kNameSpaceID_None,
+                           nsGkAtoms::aria_valuetext, aValue)) {
+      mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow,
+                        aValue);
     }
     return;
   }
 
   // Value of textbox is a textified subtree.
   if (roleMapEntry->Is(nsGkAtoms::textbox)) {
     nsTextEquivUtils::GetTextEquivFromSubtree(this, aValue);
     return;
@@ -1456,21 +1449,20 @@ Accessible::ARIATransformRole(role aRole
   // where the accessible role depends on both the role and ARIA state.
   if (aRole == roles::PUSHBUTTON) {
     if (nsAccUtils::HasDefinedARIAToken(mContent, nsGkAtoms::aria_pressed)) {
       // For simplicity, any existing pressed attribute except "" or "undefined"
       // indicates a toggle.
       return roles::TOGGLE_BUTTON;
     }
 
-    if (mContent->IsElement() &&
-        mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::aria_haspopup,
-                                           nsGkAtoms::_true,
-                                           eCaseMatters)) {
+    if (mContent->AttrValueIs(kNameSpaceID_None,
+                              nsGkAtoms::aria_haspopup,
+                              nsGkAtoms::_true,
+                              eCaseMatters)) {
       // For button with aria-haspopup="true".
       return roles::BUTTONMENU;
     }
 
   } else if (aRole == roles::LISTBOX) {
     // A listbox inside of a combobox needs a special role because of ATK
     // mapping to menu.
     if (mParent && mParent->IsCombobox()) {
@@ -1485,19 +1477,18 @@ Accessible::ARIATransformRole(role aRole
     }
 
   } else if (aRole == roles::OPTION) {
     if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
       return roles::COMBOBOX_OPTION;
 
   } else if (aRole == roles::MENUITEM) {
     // Menuitem has a submenu.
-    if (mContent->IsElement() &&
-        mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_haspopup,
-                                           nsGkAtoms::_true, eCaseMatters)) {
+    if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_haspopup,
+                              nsGkAtoms::_true, eCaseMatters)) {
       return roles::PARENT_MENUITEM;
     }
   }
 
   return aRole;
 }
 
 nsAtom*
@@ -1601,20 +1592,17 @@ Accessible::DoAction(uint8_t aIndex)
   return false;
 }
 
 nsIContent*
 Accessible::GetAtomicRegion() const
 {
   nsIContent *loopContent = mContent;
   nsAutoString atomic;
-  while (loopContent &&
-         (!loopContent->IsElement() ||
-          !loopContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                             nsGkAtoms::aria_atomic, atomic)))
+  while (loopContent && !loopContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_atomic, atomic))
     loopContent = loopContent->GetParent();
 
   return atomic.EqualsLiteral("true") ? loopContent : nullptr;
 }
 
 Relation
 Accessible::RelationByType(RelationType aType)
 {
@@ -1994,19 +1982,17 @@ Accessible::ARIAName(nsString& aName)
   // aria-labelledby now takes precedence over aria-label
   nsresult rv = nsTextEquivUtils::
     GetTextEquivFromIDRefs(this, nsGkAtoms::aria_labelledby, aName);
   if (NS_SUCCEEDED(rv)) {
     aName.CompressWhitespace();
   }
 
   if (aName.IsEmpty() &&
-      mContent->IsElement() &&
-      mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label,
-                                     aName)) {
+      mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label, aName)) {
     aName.CompressWhitespace();
   }
 }
 
 // Accessible protected
 ENameValueFlag
 Accessible::NativeName(nsString& aName)
 {
@@ -2553,32 +2539,30 @@ Accessible::IsActiveWidget() const
 
   return false;
 }
 
 bool
 Accessible::AreItemsOperable() const
 {
   return HasOwnContent() &&
-    mContent->IsElement() &&
-    mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant);
+    mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant);
 }
 
 Accessible*
 Accessible::CurrentItem()
 {
   // Check for aria-activedescendant, which changes which element has focus.
   // For activedescendant, the ARIA spec does not require that the user agent
   // checks whether pointed node is actually a DOM descendant of the element
   // with the aria-activedescendant attribute.
   nsAutoString id;
   if (HasOwnContent() &&
-      mContent->IsElement() &&
-      mContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                     nsGkAtoms::aria_activedescendant, id)) {
+      mContent->GetAttr(kNameSpaceID_None,
+                        nsGkAtoms::aria_activedescendant, id)) {
     nsIDocument* DOMDoc = mContent->OwnerDoc();
     dom::Element* activeDescendantElm = DOMDoc->GetElementById(id);
     if (activeDescendantElm) {
       DocAccessible* document = Document();
       if (document)
         return document->GetAccessible(activeDescendantElm);
     }
   }
@@ -2601,19 +2585,18 @@ Accessible::SetCurrentItem(Accessible* a
 
 Accessible*
 Accessible::ContainerWidget() const
 {
   if (HasARIARole() && mContent->HasID()) {
     for (Accessible* parent = Parent(); parent; parent = parent->Parent()) {
       nsIContent* parentContent = parent->GetContent();
       if (parentContent &&
-          parentContent->IsElement() &&
-          parentContent->AsElement()->HasAttr(kNameSpaceID_None,
-                                              nsGkAtoms::aria_activedescendant)) {
+        parentContent->HasAttr(kNameSpaceID_None,
+                               nsGkAtoms::aria_activedescendant)) {
         return parent;
       }
 
       // Don't cross DOM document boundaries.
       if (parent->IsDoc())
         break;
     }
   }
@@ -2676,34 +2659,33 @@ Accessible::GetSiblingAtOffset(int32_t a
 double
 Accessible::AttrNumericValue(nsAtom* aAttr) const
 {
   const nsRoleMapEntry* roleMapEntry = ARIARoleMap();
   if (!roleMapEntry || roleMapEntry->valueRule == eNoValue)
     return UnspecifiedNaN<double>();
 
   nsAutoString attrValue;
-  if (!mContent->IsElement() ||
-      !mContent->AsElement()->GetAttr(kNameSpaceID_None, aAttr, attrValue))
+  if (!mContent->GetAttr(kNameSpaceID_None, aAttr, attrValue))
     return UnspecifiedNaN<double>();
 
   nsresult error = NS_OK;
   double value = attrValue.ToDouble(&error);
   return NS_FAILED(error) ? UnspecifiedNaN<double>() : value;
 }
 
 uint32_t
 Accessible::GetActionRule() const
 {
   if (!HasOwnContent() || (InteractiveState() & states::UNAVAILABLE))
     return eNoAction;
 
   // Return "click" action on elements that have an attached popup menu.
   if (mContent->IsXULElement())
-    if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::popup))
+    if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::popup))
       return eClickAction;
 
   // Has registered 'click' event handler.
   bool isOnclick = nsCoreUtils::HasClickListener(mContent);
 
   if (isOnclick)
     return eClickAction;
 
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -870,17 +870,17 @@ DocAccessible::AttributeChangedImpl(Acce
     return;
   }
 
   if (aAttribute == nsGkAtoms::aria_describedby) {
     FireDelayedEvent(nsIAccessibleEvent::EVENT_DESCRIPTION_CHANGE, aAccessible);
     return;
   }
 
-  dom::Element* elm = aAccessible->GetContent()->AsElement();
+  nsIContent* elm = aAccessible->GetContent();
   if (aAttribute == nsGkAtoms::aria_labelledby &&
       !elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_label)) {
     FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, aAccessible);
     return;
   }
 
   if (aAttribute == nsGkAtoms::alt &&
       !elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_label) &&
@@ -991,17 +991,17 @@ DocAccessible::ARIAAttributeChanged(Acce
   // change event; at least until native API comes up with a more meaningful event.
   uint8_t attrFlags = aria::AttrCharacteristicsFor(aAttribute);
   if (!(attrFlags & ATTR_BYPASSOBJ)) {
     RefPtr<AccEvent> event =
       new AccObjectAttrChangedEvent(aAccessible, aAttribute);
     FireDelayedEvent(event);
   }
 
-  dom::Element* elm = aAccessible->GetContent()->AsElement();
+  nsIContent* elm = aAccessible->GetContent();
 
   // Update aria-hidden flag for the whole subtree iff aria-hidden is changed
   // on the root, i.e. ignore any affiliated aria-hidden changes in the subtree
   // of top aria-hidden.
   if (aAttribute == nsGkAtoms::aria_hidden) {
     bool isDefined = aria::HasDefinedARIAHidden(elm);
     if (isDefined != aAccessible->IsARIAHidden() &&
         (!aAccessible->Parent() || !aAccessible->Parent()->IsARIAHidden())) {
@@ -1067,21 +1067,19 @@ DocAccessible::ARIAAttributeChanged(Acce
     mNotificationController->ScheduleRelocation(aAccessible);
   }
 }
 
 void
 DocAccessible::ARIAActiveDescendantChanged(Accessible* aAccessible)
 {
   nsIContent* elm = aAccessible->GetContent();
-  if (elm && elm->IsElement() && aAccessible->IsActiveWidget()) {
+  if (elm && aAccessible->IsActiveWidget()) {
     nsAutoString id;
-    if (elm->AsElement()->GetAttr(kNameSpaceID_None,
-                                  nsGkAtoms::aria_activedescendant,
-                                  id)) {
+    if (elm->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant, id)) {
       dom::Element* activeDescendantElm = elm->OwnerDoc()->GetElementById(id);
       if (activeDescendantElm) {
         Accessible* activeDescendant = GetAccessible(activeDescendantElm);
         if (activeDescendant) {
           FocusMgr()->ActiveItemChanged(activeDescendant, false);
 #ifdef A11Y_LOG
           if (logging::IsEnabled(logging::eFocus))
             logging::ActiveItemChangeCausedBy("ARIA activedescedant changed",
@@ -1308,19 +1306,18 @@ DocAccessible::BindToDocument(Accessible
   // Put into unique ID cache.
   mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible);
 
   aAccessible->SetRoleMapEntry(aRoleMapEntry);
 
   if (aAccessible->HasOwnContent()) {
     AddDependentIDsFor(aAccessible);
 
-    nsIContent* content = aAccessible->GetContent();
-    if (content->IsElement() &&
-        content->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_owns)) {
+    nsIContent* el = aAccessible->GetContent();
+    if (el->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_owns)) {
       mNotificationController->ScheduleRelocation(aAccessible);
     }
   }
 }
 
 void
 DocAccessible::UnbindFromDocument(Accessible* aAccessible)
 {
--- a/accessible/generic/FormControlAccessible.cpp
+++ b/accessible/generic/FormControlAccessible.cpp
@@ -35,17 +35,17 @@ ProgressMeterAccessible<Max>::NativeRole
 template<int Max>
 uint64_t
 ProgressMeterAccessible<Max>::NativeState()
 {
   uint64_t state = LeafAccessible::NativeState();
 
   // An undetermined progressbar (i.e. without a value) has a mixed state.
   nsAutoString attrValue;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue);
 
   if (attrValue.IsEmpty())
     state |= states::MIXED;
 
   return state;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -89,17 +89,17 @@ template<int Max>
 double
 ProgressMeterAccessible<Max>::MaxValue() const
 {
   double value = LeafAccessible::MaxValue();
   if (!IsNaN(value))
     return value;
 
   nsAutoString strValue;
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::max, strValue)) {
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::max, strValue)) {
     nsresult result = NS_OK;
     value = strValue.ToDouble(&result);
     if (NS_SUCCEEDED(result))
       return value;
   }
 
   return Max;
 }
@@ -124,17 +124,17 @@ template<int Max>
 double
 ProgressMeterAccessible<Max>::CurValue() const
 {
   double value = LeafAccessible::CurValue();
   if (!IsNaN(value))
     return value;
 
   nsAutoString attrValue;
-  if (!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue))
+  if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue))
     return UnspecifiedNaN<double>();
 
   nsresult error = NS_OK;
   value = attrValue.ToDouble(&error);
   return NS_FAILED(error) ? UnspecifiedNaN<double>() : value;
 }
 
 template<int Max>
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -264,21 +264,22 @@ HyperTextAccessible::DOMPointToOffset(ns
     }
   }
 
   // Get accessible for this findNode, or if that node isn't accessible, use the
   // accessible for the next DOM node which has one (based on forward depth first search)
   Accessible* descendant = nullptr;
   if (findNode) {
     nsCOMPtr<nsIContent> findContent(do_QueryInterface(findNode));
-    if (findContent && findContent->IsHTMLElement(nsGkAtoms::br) &&
-        findContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                              nsGkAtoms::mozeditorbogusnode,
-                                              nsGkAtoms::_true,
-                                              eIgnoreCase)) {
+    if (findContent && findContent->IsHTMLElement() &&
+        findContent->NodeInfo()->Equals(nsGkAtoms::br) &&
+        findContent->AttrValueIs(kNameSpaceID_None,
+                                 nsGkAtoms::mozeditorbogusnode,
+                                 nsGkAtoms::_true,
+                                 eIgnoreCase)) {
       // This <br> is the hacky "bogus node" used when there is no text in a control
       return 0;
     }
 
     descendant = mDoc->GetAccessible(findNode);
     if (!descendant && findNode->IsContent()) {
       Accessible* container = mDoc->GetContainerAccessible(findNode);
       if (container) {
@@ -1846,31 +1847,30 @@ HyperTextAccessible::RangeAtPoint(int32_
 
 // Accessible protected
 ENameValueFlag
 HyperTextAccessible::NativeName(nsString& aName)
 {
   // Check @alt attribute for invalid img elements.
   bool hasImgAlt = false;
   if (mContent->IsHTMLElement(nsGkAtoms::img)) {
-    hasImgAlt =
-      mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName);
+    hasImgAlt = mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName);
     if (!aName.IsEmpty())
       return eNameOK;
   }
 
   ENameValueFlag nameFlag = AccessibleWrap::NativeName(aName);
   if (!aName.IsEmpty())
     return nameFlag;
 
   // Get name from title attribute for HTML abbr and acronym elements making it
   // a valid name from markup. Otherwise their name isn't picked up by recursive
   // name computation algorithm. See NS_OK_NAME_FROM_TOOLTIP.
   if (IsAbbreviation() &&
-      mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName))
+      mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName))
     aName.CompressWhitespace();
 
   return hasImgAlt ? eNoNameOnPurpose : eNameOK;
 }
 
 void
 HyperTextAccessible::Shutdown()
 {
--- a/accessible/generic/ImageAccessible.cpp
+++ b/accessible/generic/ImageAccessible.cpp
@@ -69,17 +69,17 @@ ImageAccessible::NativeState()
 
   return state;
 }
 
 ENameValueFlag
 ImageAccessible::NativeName(nsString& aName)
 {
   bool hasAltAttrib =
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName);
   if (!aName.IsEmpty())
     return eNameOK;
 
   ENameValueFlag nameFlag = Accessible::NativeName(aName);
   if (!aName.IsEmpty())
     return nameFlag;
 
   // No accessible name but empty 'alt' attribute is present. If further name
@@ -162,33 +162,33 @@ ImageAccessible::Size()
 // Accessible
 already_AddRefed<nsIPersistentProperties>
 ImageAccessible::NativeAttributes()
 {
   nsCOMPtr<nsIPersistentProperties> attributes =
     LinkableAccessible::NativeAttributes();
 
   nsAutoString src;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
   if (!src.IsEmpty())
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::src, src);
 
   return attributes.forget();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Private methods
 
 already_AddRefed<nsIURI>
 ImageAccessible::GetLongDescURI() const
 {
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::longdesc)) {
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::longdesc)) {
     // To check if longdesc contains an invalid url.
     nsAutoString longdesc;
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::longdesc, longdesc);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::longdesc, longdesc);
     if (longdesc.FindChar(' ') != -1 || longdesc.FindChar('\t') != -1 ||
         longdesc.FindChar('\r') != -1 || longdesc.FindChar('\n') != -1) {
       return nullptr;
     }
     nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
     nsCOMPtr<nsIURI> uri;
     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri), longdesc,
                                               mContent->OwnerDoc(), baseURI);
@@ -196,17 +196,17 @@ ImageAccessible::GetLongDescURI() const
   }
 
   DocAccessible* document = Document();
   if (document) {
     IDRefsIterator iter(document, mContent, nsGkAtoms::aria_describedby);
     while (nsIContent* target = iter.NextElem()) {
       if ((target->IsHTMLElement(nsGkAtoms::a) ||
            target->IsHTMLElement(nsGkAtoms::area)) &&
-          target->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
+          target->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
         nsGenericHTMLElement* element =
           nsGenericHTMLElement::FromContent(target);
 
         nsCOMPtr<nsIURI> uri;
         element->GetURIAttr(nsGkAtoms::href, nullptr, getter_AddRefs(uri));
         return uri.forget();
       }
     }
--- a/accessible/html/HTMLFormControlAccessible.cpp
+++ b/accessible/html/HTMLFormControlAccessible.cpp
@@ -126,19 +126,19 @@ void
 HTMLRadioButtonAccessible::GetPositionAndSizeInternal(int32_t* aPosInSet,
                                                       int32_t* aSetSize)
 {
   int32_t namespaceId = mContent->NodeInfo()->NamespaceID();
   nsAutoString tagName;
   mContent->NodeInfo()->GetName(tagName);
 
   nsAutoString type;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
   nsAutoString name;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
 
   RefPtr<nsContentList> inputElms;
 
   nsCOMPtr<nsIFormControl> formControlNode(do_QueryInterface(mContent));
   dom::Element* formElm = formControlNode->GetFormElement();
   if (formElm)
     inputElms = NS_GetContentList(formElm, namespaceId, tagName);
   else
@@ -148,21 +148,20 @@ HTMLRadioButtonAccessible::GetPositionAn
   uint32_t inputCount = inputElms->Length(false);
 
   // Compute posinset and setsize.
   int32_t indexOf = 0;
   int32_t count = 0;
 
   for (uint32_t index = 0; index < inputCount; index++) {
     nsIContent* inputElm = inputElms->Item(index, false);
-    if (inputElm->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                           type, eCaseMatters) &&
-        inputElm->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
-                                           name, eCaseMatters) &&
-        mDoc->HasAccessible(inputElm)) {
+    if (inputElm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                              type, eCaseMatters) &&
+        inputElm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+                              name, eCaseMatters) && mDoc->HasAccessible(inputElm)) {
         count++;
       if (inputElm == mContent)
         indexOf = count;
     }
   }
 
   *aPosInSet = indexOf;
   *aSetSize = count;
@@ -248,22 +247,22 @@ HTMLButtonAccessible::NativeName(nsStrin
   // element that has no valid @src (note if input@type="image" has an image
   // then neither @alt nor @value attributes are used to generate a visual label
   // and thus we need to obtain the accessible name directly from attribute
   // value). Also the same algorithm works in case of default labels for
   // type="submit"/"reset"/"image" elements.
 
   ENameValueFlag nameFlag = Accessible::NativeName(aName);
   if (!aName.IsEmpty() || !mContent->IsHTMLElement(nsGkAtoms::input) ||
-      !mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                          nsGkAtoms::image, eCaseMatters))
+      !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                             nsGkAtoms::image, eCaseMatters))
     return nameFlag;
 
-  if (!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
+  if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
 
   aName.CompressWhitespace();
   return eNameOK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLButtonAccessible: Widgets
 
@@ -286,34 +285,34 @@ HTMLTextFieldAccessible::
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLTextFieldAccessible,
                              HyperTextAccessible)
 
 role
 HTMLTextFieldAccessible::NativeRole()
 {
-  if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                         nsGkAtoms::password, eIgnoreCase)) {
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::password, eIgnoreCase)) {
     return roles::PASSWORD_TEXT;
   }
 
   return roles::ENTRY;
 }
 
 already_AddRefed<nsIPersistentProperties>
 HTMLTextFieldAccessible::NativeAttributes()
 {
   nsCOMPtr<nsIPersistentProperties> attributes =
     HyperTextAccessibleWrap::NativeAttributes();
 
   // Expose type for text input elements as it gives some useful context,
   // especially for mobile.
   nsAutoString type;
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textInputType, type);
     if (!ARIARoleMap() && type.EqualsLiteral("search")) {
       nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                              NS_LITERAL_STRING("searchbox"));
     }
   }
 
   return attributes.forget();
@@ -330,17 +329,17 @@ HTMLTextFieldAccessible::NativeName(nsSt
   nsIContent* widgetElm = XULWidgetElm();
   if (widgetElm)
     XULElmName(mDoc, widgetElm, aName);
 
   if (!aName.IsEmpty())
     return eNameOK;
 
   // text inputs and textareas might have useful placeholder text
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, aName);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, aName);
   return eNameOK;
 }
 
 void
 HTMLTextFieldAccessible::Value(nsString& aValue)
 {
   aValue.Truncate();
   if (NativeState() & states::PROTECTED)    // Don't return password text!
@@ -378,22 +377,22 @@ HTMLTextFieldAccessible::NativeState()
 {
   uint64_t state = HyperTextAccessibleWrap::NativeState();
 
   // Text fields are always editable, even if they are also read only or
   // disabled.
   state |= states::EDITABLE;
 
   // can be focusable, focused, protected. readonly, unavailable, selected
-  if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                         nsGkAtoms::password, eIgnoreCase)) {
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::password, eIgnoreCase)) {
     state |= states::PROTECTED;
   }
 
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly)) {
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly)) {
     state |= states::READONLY;
   }
 
   // Is it an <input> or a <textarea> ?
   HTMLInputElement* input = HTMLInputElement::FromContent(mContent);
   state |= input && input->IsSingleLineTextControl() ?
     states::SINGLE_LINE : states::MULTI_LINE;
 
@@ -404,38 +403,38 @@ HTMLTextFieldAccessible::NativeState()
   // Expose autocomplete states if this input is part of autocomplete widget.
   Accessible* widget = ContainerWidget();
   if (widget && widget-IsAutoComplete()) {
     state |= states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION;
     return state;
   }
 
   // Expose autocomplete state if it has associated autocomplete list.
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::list))
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::list))
     return state | states::SUPPORTS_AUTOCOMPLETION | states::HASPOPUP;
 
   // Ordinal XUL textboxes don't support autocomplete.
   if (!XULWidgetElm() && Preferences::GetBool("browser.formfill.enable")) {
     // Check to see if autocompletion is allowed on this input. We don't expose
     // it for password fields even though the entire password can be remembered
     // for a page if the user asks it to be. However, the kind of autocomplete
     // we're talking here is based on what the user types, where a popup of
     // possible choices comes up.
     nsAutoString autocomplete;
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::autocomplete,
-                                   autocomplete);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::autocomplete,
+                      autocomplete);
 
     if (!autocomplete.LowerCaseEqualsLiteral("off")) {
-      Element* formElement = input->GetFormElement();
-      if (formElement) {
-        formElement->GetAttr(kNameSpaceID_None,
+      nsIContent* formContent = input->GetFormElement();
+      if (formContent) {
+        formContent->GetAttr(kNameSpaceID_None,
                              nsGkAtoms::autocomplete, autocomplete);
       }
 
-      if (!formElement || !autocomplete.LowerCaseEqualsLiteral("off"))
+      if (!formContent || !autocomplete.LowerCaseEqualsLiteral("off"))
         state |= states::SUPPORTS_AUTOCOMPLETION;
     }
   }
 
   return state;
 }
 
 uint8_t
--- a/accessible/html/HTMLImageMapAccessible.cpp
+++ b/accessible/html/HTMLImageMapAccessible.cpp
@@ -150,30 +150,29 @@ HTMLAreaAccessible::
 
 ENameValueFlag
 HTMLAreaAccessible::NativeName(nsString& aName)
 {
   ENameValueFlag nameFlag = Accessible::NativeName(aName);
   if (!aName.IsEmpty())
     return nameFlag;
 
-  if (!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
+  if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
     Value(aName);
 
   return eNameOK;
 }
 
 void
 HTMLAreaAccessible::Description(nsString& aDescription)
 {
   aDescription.Truncate();
 
   // Still to do - follow IE's standard here
-  RefPtr<dom::HTMLAreaElement> area =
-    dom::HTMLAreaElement::FromContentOrNull(mContent);
+  RefPtr<HTMLAreaElement> area = HTMLAreaElement::FromContentOrNull(mContent);
   if (area)
     area->GetShape(aDescription);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLAreaAccessible: Accessible public
 
 Accessible*
--- a/accessible/html/HTMLLinkAccessible.cpp
+++ b/accessible/html/HTMLLinkAccessible.cpp
@@ -63,17 +63,17 @@ HTMLLinkAccessible::NativeLinkState() co
 uint64_t
 HTMLLinkAccessible::NativeInteractiveState() const
 {
   uint64_t state = HyperTextAccessibleWrap::NativeInteractiveState();
 
   // This is how we indicate it is a named anchor. In other words, this anchor
   // can be selected as a location :) There is no other better state to use to
   // indicate this.
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::name))
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::name))
     state |= states::SELECTABLE;
 
   return state;
 }
 
 void
 HTMLLinkAccessible::Value(nsString& aValue)
 {
--- a/accessible/html/HTMLSelectAccessible.cpp
+++ b/accessible/html/HTMLSelectAccessible.cpp
@@ -37,17 +37,17 @@ HTMLSelectListAccessible::
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLSelectListAccessible: Accessible public
 
 uint64_t
 HTMLSelectListAccessible::NativeState()
 {
   uint64_t state = AccessibleWrap::NativeState();
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple))
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple))
     state |= states::MULTISELECTABLE | states::EXTSELECTABLE;
 
   return state;
 }
 
 role
 HTMLSelectListAccessible::NativeRole()
 {
@@ -55,24 +55,24 @@ HTMLSelectListAccessible::NativeRole()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLSelectListAccessible: SelectAccessible
 
 bool
 HTMLSelectListAccessible::SelectAll()
 {
-  return mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
+  return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
     AccessibleWrap::SelectAll() : false;
 }
 
 bool
 HTMLSelectListAccessible::UnselectAll()
 {
-  return mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
+  return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
     AccessibleWrap::UnselectAll() : false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLSelectListAccessible: Widgets
 
 bool
 HTMLSelectListAccessible::IsWidget() const
@@ -147,17 +147,17 @@ HTMLSelectOptionAccessible::NativeRole()
   return roles::OPTION;
 }
 
 ENameValueFlag
 HTMLSelectOptionAccessible::NativeName(nsString& aName)
 {
   // CASE #1 -- great majority of the cases
   // find the label attribute - this is what the W3C says we should use
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
   if (!aName.IsEmpty())
     return eNameOK;
 
   // CASE #2 -- no label parameter, get the first child,
   // use it if it is a text node
   nsIContent* text = mContent->GetFirstChild();
   if (text && text->IsNodeOfType(nsINode::eTEXT)) {
     nsTextEquivUtils::AppendTextEquivFromTextContent(text, &aName);
--- a/accessible/html/HTMLTableAccessible.cpp
+++ b/accessible/html/HTMLTableAccessible.cpp
@@ -117,24 +117,24 @@ HTMLTableCellAccessible::NativeAttribute
       nsIContent* firstChildNode = abbr->GetContent()->GetFirstChild();
       if (firstChildNode) {
         nsTextEquivUtils::
           AppendTextEquivFromTextContent(firstChildNode, &abbrText);
       }
     }
   }
   if (abbrText.IsEmpty())
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::abbr, abbrText);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::abbr, abbrText);
 
   if (!abbrText.IsEmpty())
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::abbr, abbrText);
 
   // axis attribute
   nsAutoString axisText;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::axis, axisText);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::axis, axisText);
   if (!axisText.IsEmpty())
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::axis, axisText);
 
 #ifdef DEBUG
   nsAutoString unused;
   attributes->SetStringProperty(NS_LITERAL_CSTRING("cppclass"),
                                 NS_LITERAL_STRING("HTMLTableCellAccessible"),
                                 unused);
@@ -307,22 +307,22 @@ HTMLTableHeaderCellAccessible::
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableHeaderCellAccessible: Accessible implementation
 
 role
 HTMLTableHeaderCellAccessible::NativeRole()
 {
   // Check value of @scope attribute.
-  static Element::AttrValuesArray scopeValues[] =
+  static nsIContent::AttrValuesArray scopeValues[] =
     { &nsGkAtoms::col, &nsGkAtoms::colgroup,
       &nsGkAtoms::row, &nsGkAtoms::rowgroup, nullptr };
   int32_t valueIdx =
-    mContent->AsElement()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::scope,
-                                           scopeValues, eCaseMatters);
+    mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::scope,
+                              scopeValues, eCaseMatters);
 
   switch (valueIdx) {
     case 0:
     case 1:
       return roles::COLUMNHEADER;
     case 2:
     case 3:
       return roles::ROWHEADER;
@@ -432,17 +432,17 @@ HTMLTableAccessible::NativeName(nsString
     if (captionContent) {
       nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
       if (!aName.IsEmpty())
         return eNameOK;
     }
   }
 
   // If no caption then use summary as a name.
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, aName);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, aName);
   return eNameOK;
 }
 
 already_AddRefed<nsIPersistentProperties>
 HTMLTableAccessible::NativeAttributes()
 {
   nsCOMPtr<nsIPersistentProperties> attributes =
     AccessibleWrap::NativeAttributes();
@@ -858,18 +858,18 @@ HTMLTableAccessible::Description(nsStrin
   if (caption) {
     nsIContent* captionContent = caption->GetContent();
     if (captionContent) {
       nsAutoString captionText;
       nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent,
                                                    &captionText);
 
       if (!captionText.IsEmpty()) { // summary isn't used as a name.
-        mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::summary,
-                                       aDescription);
+        mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary,
+                          aDescription);
       }
     }
   }
 
 #ifdef SHOW_LAYOUT_HEURISTIC
   if (aDescription.IsEmpty()) {
     bool isProbablyForLayout = IsProbablyLayoutTable();
     aDescription = mLayoutHeuristic;
@@ -941,35 +941,35 @@ HTMLTableAccessible::IsProbablyLayoutTab
     }
   }
 
   // Check to see if an ARIA role overrides the role from native markup,
   // but for which we still expose table semantics (treegrid, for example).
   if (Role() != roles::TABLE)
     RETURN_LAYOUT_ANSWER(false, "Has role attribute");
 
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
     // Role attribute is present, but overridden roles have already been dealt with.
     // Only landmarks and other roles that don't override the role from native
     // markup are left to deal with here.
     RETURN_LAYOUT_ANSWER(false, "Has role attribute, weak role, and role is table");
   }
 
   NS_ASSERTION(mContent->IsHTMLElement(nsGkAtoms::table),
     "table should not be built by CSS display:table style");
 
   // Check if datatable attribute has "0" value.
-  if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::datatable,
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::datatable,
                             NS_LITERAL_STRING("0"), eCaseMatters)) {
     RETURN_LAYOUT_ANSWER(true, "Has datatable = 0 attribute, it's for layout");
   }
 
   // Check for legitimate data table attributes.
   nsAutoString summary;
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, summary) &&
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, summary) &&
       !summary.IsEmpty())
     RETURN_LAYOUT_ANSWER(false, "Has summary -- legitimate table structures");
 
   // Check for legitimate data table elements.
   Accessible* caption = FirstChild();
   if (caption && caption->Role() == roles::CAPTION && caption->HasChildren())
     RETURN_LAYOUT_ANSWER(false, "Not empty caption -- legitimate table structures");
 
@@ -994,19 +994,19 @@ HTMLTableAccessible::IsProbablyLayoutTab
                cellElm = cellElm->GetNextSibling()) {
             if (cellElm->IsHTMLElement()) {
 
               if (cellElm->NodeInfo()->Equals(nsGkAtoms::th)) {
                 RETURN_LAYOUT_ANSWER(false,
                                      "Has th -- legitimate table structures");
               }
 
-              if (cellElm->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::headers) ||
-                  cellElm->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::scope) ||
-                  cellElm->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::abbr)) {
+              if (cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::headers) ||
+                  cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::scope) ||
+                  cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::abbr)) {
                 RETURN_LAYOUT_ANSWER(false,
                                      "Has headers, scope, or abbr attribute -- legitimate table structures");
               }
 
               Accessible* cell = mDoc->GetAccessible(cellElm);
               if (cell && cell->ChildCount() == 1 &&
                   cell->FirstChild()->IsAbbreviation()) {
                 RETURN_LAYOUT_ANSWER(false,
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -491,17 +491,17 @@ AccessibleWrap::get_accRole(
   // Use BSTR role to expose role attribute or tag name + namespace
   nsIContent *content = GetContent();
   if (!content)
     return E_FAIL;
 
   if (content->IsElement()) {
     nsAutoString roleString;
     // Try the role attribute.
-    content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roleString);
+    content->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roleString);
 
     if (roleString.IsEmpty()) {
       // No role attribute (or it is an empty string).
       // Use the tag name.
       nsIDocument * document = content->GetUncomposedDoc();
       if (!document)
         return E_FAIL;
 
--- a/accessible/windows/msaa/XULMenuAccessibleWrap.cpp
+++ b/accessible/windows/msaa/XULMenuAccessibleWrap.cpp
@@ -23,16 +23,14 @@ XULMenuitemAccessibleWrap::Name(nsString
 {
   // XXX This should be done in MSAA's get_accName() so that Accessible::Name()]
   // provides the same results on all platforms
   XULMenuitemAccessible::Name(aName);
   if (aName.IsEmpty())
     return eNameOK;
 
   nsAutoString accel;
-  if (mContent->IsElement()) {
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::acceltext, accel);
-  }
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::acceltext, accel);
   if (!accel.IsEmpty())
     aName += NS_LITERAL_STRING("\t") + accel;
 
   return eNameOK;
 }
--- a/accessible/xul/XULColorPickerAccessible.cpp
+++ b/accessible/xul/XULColorPickerAccessible.cpp
@@ -30,30 +30,30 @@ XULColorPickerTileAccessible::
 ////////////////////////////////////////////////////////////////////////////////
 // XULColorPickerTileAccessible: Accessible
 
 void
 XULColorPickerTileAccessible::Value(nsString& aValue)
 {
   aValue.Truncate();
 
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::color, aValue);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::color, aValue);
 }
 
 role
 XULColorPickerTileAccessible::NativeRole()
 {
   return roles::PUSHBUTTON;
 }
 
 uint64_t
 XULColorPickerTileAccessible::NativeState()
 {
   uint64_t state = AccessibleWrap::NativeState();
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::selected))
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::selected))
     state |= states::SELECTED;
 
   return state;
 }
 
 uint64_t
 XULColorPickerTileAccessible::NativeInteractiveState() const
 {
@@ -133,12 +133,11 @@ XULColorPickerAccessible::AreItemsOperab
 // XULColorPickerAccessible: Accessible
 
 bool
 XULColorPickerAccessible::IsAcceptableChild(nsIContent* aEl) const
 {
   nsAutoString role;
   nsCoreUtils::XBLBindingRole(aEl, role);
   return role.EqualsLiteral("xul:panel") &&
-    aEl->IsElement() &&
-    aEl->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautofocus,
-                                  nsGkAtoms::_true, eCaseMatters);
+    aEl->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautofocus,
+                     nsGkAtoms::_true, eCaseMatters);
 }
--- a/accessible/xul/XULComboboxAccessible.cpp
+++ b/accessible/xul/XULComboboxAccessible.cpp
@@ -21,29 +21,28 @@ using namespace mozilla::a11y;
 ////////////////////////////////////////////////////////////////////////////////
 // XULComboboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULComboboxAccessible::
   XULComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
 {
-  if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                         nsGkAtoms::autocomplete, eIgnoreCase))
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::autocomplete, eIgnoreCase))
     mGenericTypes |= eAutoComplete;
   else
     mGenericTypes |= eCombobox;
 
   // Both the XUL <textbox type="autocomplete"> and <menulist editable="true">
   // widgets use XULComboboxAccessible. We need to walk the anonymous children
   // for these so that the entry field is a child. Otherwise no XBL children.
   if (!mContent->NodeInfo()->Equals(nsGkAtoms::textbox, kNameSpaceID_XUL) &&
-      !mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                          nsGkAtoms::editable, nsGkAtoms::_true,
-                                          eIgnoreCase)) {
+      !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
+                             nsGkAtoms::_true, eIgnoreCase)) {
     mStateFlags |= eNoXBLKids;
   }
 }
 
 role
 XULComboboxAccessible::NativeRole()
 {
   return IsAutoComplete() ? roles::AUTOCOMPLETE : roles::COMBOBOX;
@@ -151,18 +150,18 @@ XULComboboxAccessible::ActionNameAt(uint
 
 ////////////////////////////////////////////////////////////////////////////////
 // Widgets
 
 bool
 XULComboboxAccessible::IsActiveWidget() const
 {
   if (IsAutoComplete() ||
-     mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
-                                        nsGkAtoms::_true, eIgnoreCase)) {
+     mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
+                           nsGkAtoms::_true, eIgnoreCase)) {
     int32_t childCount = mChildren.Length();
     for (int32_t idx = 0; idx < childCount; idx++) {
       Accessible* child = mChildren[idx];
       if (child->Role() == roles::ENTRY)
         return FocusMgr()->HasDOMFocus(child->GetContent());
     }
     return false;
   }
--- a/accessible/xul/XULElementAccessibles.cpp
+++ b/accessible/xul/XULElementAccessibles.cpp
@@ -179,23 +179,23 @@ XULLinkAccessible::~XULLinkAccessible()
 ////////////////////////////////////////////////////////////////////////////////
 // XULLinkAccessible: Accessible
 
 void
 XULLinkAccessible::Value(nsString& aValue)
 {
   aValue.Truncate();
 
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::href, aValue);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, aValue);
 }
 
 ENameValueFlag
 XULLinkAccessible::NativeName(nsString& aName)
 {
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
   if (!aName.IsEmpty())
     return eNameOK;
 
   nsTextEquivUtils::GetNameFromSubtree(this, aName);
   return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
 }
 
 role
@@ -269,17 +269,17 @@ XULLinkAccessible::EndOffset()
 
 already_AddRefed<nsIURI>
 XULLinkAccessible::AnchorURIAt(uint32_t aAnchorIndex)
 {
   if (aAnchorIndex != 0)
     return nullptr;
 
   nsAutoString href;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
 
   nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
   nsIDocument* document = mContent->OwnerDoc();
 
   nsCOMPtr<nsIURI> anchorURI;
   NS_NewURI(getter_AddRefs(anchorURI), href,
             document->GetDocumentCharacterSet(),
             baseURI);
--- a/accessible/xul/XULFormControlAccessible.cpp
+++ b/accessible/xul/XULFormControlAccessible.cpp
@@ -117,17 +117,17 @@ XULButtonAccessible::NativeState()
         }
       }
     }
   }
 
   if (ContainsMenu())
     state |= states::HASPOPUP;
 
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::_default))
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::_default))
     state |= states::DEFAULT;
 
   return state;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULButtonAccessible: Widgets
 
@@ -184,32 +184,32 @@ XULButtonAccessible::IsAcceptableChild(n
   // Button type="menu-button" contains a real button. Get an accessible
   // for it. Ignore dropmarker button which is placed as a last child.
   if ((!role.EqualsLiteral("xul:button") &&
        !role.EqualsLiteral("xul:toolbarbutton")) ||
       aEl->IsXULElement(nsGkAtoms::dropMarker)) {
     return false;
   }
 
-  return mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                            nsGkAtoms::menuButton, eCaseMatters);
+  return mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                               nsGkAtoms::menuButton, eCaseMatters);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULButtonAccessible protected
 
 bool
 XULButtonAccessible::ContainsMenu() const
 {
-  static Element::AttrValuesArray strings[] =
+  static nsIContent::AttrValuesArray strings[] =
     {&nsGkAtoms::menu, &nsGkAtoms::menuButton, nullptr};
 
-  return mContent->AsElement()->FindAttrValueIn(kNameSpaceID_None,
-                                                nsGkAtoms::type,
-                                                strings, eCaseMatters) >= 0;
+  return mContent->FindAttrValueIn(kNameSpaceID_None,
+                                   nsGkAtoms::type,
+                                   strings, eCaseMatters) >= 0;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULDropmarkerAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULDropmarkerAccessible::
   XULDropmarkerAccessible(nsIContent* aContent, DocAccessible* aDoc) :
@@ -598,17 +598,17 @@ role
 XULToolbarAccessible::NativeRole()
 {
   return roles::TOOLBAR;
 }
 
 ENameValueFlag
 XULToolbarAccessible::NativeName(nsString& aName)
 {
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::toolbarname, aName))
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::toolbarname, aName))
     aName.CompressWhitespace();
 
   return eNameOK;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULToolbarAccessible
--- a/accessible/xul/XULListboxAccessible.cpp
+++ b/accessible/xul/XULListboxAccessible.cpp
@@ -121,18 +121,18 @@ XULListboxAccessible::NativeState()
   // As a XULListboxAccessible we can have the following states:
   //   FOCUSED, READONLY, FOCUSABLE
 
   // Get focus status from base class
   uint64_t states = Accessible::NativeState();
 
   // see if we are multiple select if so set ourselves as such
 
-  if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype,
-                                         nsGkAtoms::multiple, eCaseMatters)) {
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype,
+                            nsGkAtoms::multiple, eCaseMatters)) {
       states |= states::MULTISELECTABLE | states::EXTSELECTABLE;
   }
 
   return states;
 }
 
 /**
   * Our value is the label of our ( first ) selected child.
@@ -531,20 +531,20 @@ XULListboxAccessible::ContainerWidget() 
 ////////////////////////////////////////////////////////////////////////////////
 // XULListitemAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULListitemAccessible::
   XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   XULMenuitemAccessible(aContent, aDoc)
 {
-  mIsCheckbox = mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                   nsGkAtoms::type,
-                                                   nsGkAtoms::checkbox,
-                                                   eCaseMatters);
+  mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None,
+                                      nsGkAtoms::type,
+                                      nsGkAtoms::checkbox,
+                                      eCaseMatters);
   mType = eXULListItemType;
 
   // Walk XBL anonymous children for list items. Overrides the flag value from
   // base XULMenuitemAccessible class.
   mStateFlags &= ~eNoXBLKids;
 }
 
 XULListitemAccessible::~XULListitemAccessible()
@@ -592,17 +592,17 @@ XULListitemAccessible::Description(nsStr
   */
 ENameValueFlag
 XULListitemAccessible::NativeName(nsString& aName)
 {
   nsIContent* childContent = mContent->GetFirstChild();
   if (childContent) {
     if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell,
                                          kNameSpaceID_XUL)) {
-      childContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
+      childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
       return eNameOK;
     }
   }
 
   return Accessible::NativeName(aName);
 }
 
 role
--- a/accessible/xul/XULMenuAccessible.cpp
+++ b/accessible/xul/XULMenuAccessible.cpp
@@ -47,35 +47,35 @@ XULMenuitemAccessible::
 uint64_t
 XULMenuitemAccessible::NativeState()
 {
   uint64_t state = Accessible::NativeState();
 
   // Has Popup?
   if (mContent->NodeInfo()->Equals(nsGkAtoms::menu, kNameSpaceID_XUL)) {
     state |= states::HASPOPUP;
-    if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::open))
+    if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::open))
       state |= states::EXPANDED;
     else
       state |= states::COLLAPSED;
   }
 
   // Checkable/checked?
-  static Element::AttrValuesArray strings[] =
+  static nsIContent::AttrValuesArray strings[] =
     { &nsGkAtoms::radio, &nsGkAtoms::checkbox, nullptr };
 
-  if (mContent->AsElement()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type,
-                                             strings, eCaseMatters) >= 0) {
+  if (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, strings,
+                                eCaseMatters) >= 0) {
 
     // Checkable?
     state |= states::CHECKABLE;
 
     // Checked?
-    if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked,
-                                           nsGkAtoms::_true, eCaseMatters))
+    if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked,
+                              nsGkAtoms::_true, eCaseMatters))
       state |= states::CHECKED;
   }
 
   // Combo box listitem
   bool isComboboxOption = (Role() == roles::COMBOBOX_OPTION);
   if (isComboboxOption) {
     // Is selected?
     bool isSelected = false;
@@ -132,38 +132,38 @@ XULMenuitemAccessible::NativeInteractive
   }
 
   return states::FOCUSABLE | states::SELECTABLE;
 }
 
 ENameValueFlag
 XULMenuitemAccessible::NativeName(nsString& aName)
 {
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
   return eNameOK;
 }
 
 void
 XULMenuitemAccessible::Description(nsString& aDescription)
 {
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::description,
-                                 aDescription);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::description,
+                    aDescription);
 }
 
 KeyBinding
 XULMenuitemAccessible::AccessKey() const
 {
   // Return menu accesskey: N or Alt+F.
   static int32_t gMenuAccesskeyModifier = -1;  // magic value of -1 indicates unitialized state
 
   // We do not use nsCoreUtils::GetAccesskeyFor() because accesskeys for
   // menu are't registered by EventStateManager.
   nsAutoString accesskey;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey,
-                                 accesskey);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey,
+                    accesskey);
   if (accesskey.IsEmpty())
     return KeyBinding();
 
   uint32_t modifierKey = 0;
 
   Accessible* parentAcc = Parent();
   if (parentAcc) {
     if (parentAcc->NativeRole() == roles::MENUBAR) {
@@ -193,21 +193,21 @@ XULMenuitemAccessible::AccessKey() const
 
   return KeyBinding(accesskey[0], modifierKey);
 }
 
 KeyBinding
 XULMenuitemAccessible::KeyboardShortcut() const
 {
   nsAutoString keyElmId;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyElmId);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyElmId);
   if (keyElmId.IsEmpty())
     return KeyBinding();
 
-  Element* keyElm = mContent->OwnerDoc()->GetElementById(keyElmId);
+  nsIContent* keyElm = mContent->OwnerDoc()->GetElementById(keyElmId);
   if (!keyElm)
     return KeyBinding();
 
   uint32_t key = 0;
 
   nsAutoString keyStr;
   keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyStr);
   if (keyStr.IsEmpty()) {
@@ -248,22 +248,23 @@ XULMenuitemAccessible::NativeRole()
 {
   nsCOMPtr<nsIDOMXULContainerElement> xulContainer(do_QueryInterface(mContent));
   if (xulContainer)
     return roles::PARENT_MENUITEM;
 
   if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
     return roles::COMBOBOX_OPTION;
 
-  if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                         nsGkAtoms::radio, eCaseMatters))
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::radio, eCaseMatters))
     return roles::RADIO_MENU_ITEM;
 
-  if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                                         nsGkAtoms::checkbox, eCaseMatters))
+  if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::checkbox,
+                            eCaseMatters))
     return roles::CHECK_MENU_ITEM;
 
   return roles::MENUITEM;
 }
 
 int32_t
 XULMenuitemAccessible::GetLevelInternal()
 {
@@ -415,24 +416,23 @@ XULMenupopupAccessible::
 
 uint64_t
 XULMenupopupAccessible::NativeState()
 {
   uint64_t state = Accessible::NativeState();
 
 #ifdef DEBUG
   // We are onscreen if our parent is active
-  bool isActive =
-    mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::menuactive);
+  bool isActive = mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::menuactive);
   if (!isActive) {
     Accessible* parent = Parent();
     if (parent) {
       nsIContent* parentContent = parent->GetContent();
-      if (parentContent && parentContent->IsElement())
-        isActive = parentContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::open);
+      if (parentContent)
+        isActive = parentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::open);
     }
   }
 
   NS_ASSERTION(isActive || (state & states::INVISIBLE),
                "XULMenupopup doesn't have INVISIBLE when it's inactive");
 #endif
 
   if (state & states::INVISIBLE)
@@ -441,19 +441,17 @@ XULMenupopupAccessible::NativeState()
   return state;
 }
 
 ENameValueFlag
 XULMenupopupAccessible::NativeName(nsString& aName)
 {
   nsIContent* content = mContent;
   while (content && aName.IsEmpty()) {
-    if (content->IsElement()) {
-      content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
-    }
+    content->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
     content = content->GetFlattenedTreeParent();
   }
 
   return eNameOK;
 }
 
 role
 XULMenupopupAccessible::NativeRole()
--- a/accessible/xul/XULSliderAccessible.cpp
+++ b/accessible/xul/XULSliderAccessible.cpp
@@ -49,18 +49,18 @@ XULSliderAccessible::NativeInteractiveSt
   }
 
   return 0;
 }
 
 bool
 XULSliderAccessible::NativelyUnavailable() const
 {
-  return mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
-                                            nsGkAtoms::_true, eCaseMatters);
+  return mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
+                               nsGkAtoms::_true, eCaseMatters);
 }
 
 void
 XULSliderAccessible::Value(nsString& aValue)
 {
   GetSliderAttr(nsGkAtoms::curpos, aValue);
 }
 
@@ -146,17 +146,17 @@ XULSliderAccessible::GetSliderElement() 
 nsresult
 XULSliderAccessible::GetSliderAttr(nsAtom* aName, nsAString& aValue) const
 {
   aValue.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  Element* sliderElm = GetSliderElement();
+  nsIContent* sliderElm = GetSliderElement();
   if (sliderElm)
     sliderElm->GetAttr(kNameSpaceID_None, aName, aValue);
 
   return NS_OK;
 }
 
 nsresult
 XULSliderAccessible::SetSliderAttr(nsAtom* aName, const nsAString& aValue)
--- a/accessible/xul/XULTabAccessible.cpp
+++ b/accessible/xul/XULTabAccessible.cpp
@@ -80,18 +80,18 @@ XULTabAccessible::NativeState()
 
   // Check whether the tab is selected and/or pinned
   nsCOMPtr<nsIDOMXULSelectControlItemElement> tab(do_QueryInterface(mContent));
   if (tab) {
     bool selected = false;
     if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected)
       state |= states::SELECTED;
 
-    if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::pinned,
-                                           nsGkAtoms::_true, eCaseMatters))
+    if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::pinned,
+                              nsGkAtoms::_true, eCaseMatters))
       state |= states::PINNED;
 
   }
 
   return state;
 }
 
 uint64_t
--- a/accessible/xul/XULTreeGridAccessible.cpp
+++ b/accessible/xul/XULTreeGridAccessible.cpp
@@ -817,19 +817,19 @@ XULTreeGridCellAccessible::IsEditable() 
   if (NS_FAILED(rv) || !isEditable)
     return false;
 
   nsCOMPtr<nsIDOMElement> columnElm;
   mColumn->GetElement(getter_AddRefs(columnElm));
   if (!columnElm)
     return false;
 
-  nsCOMPtr<Element> columnContent(do_QueryInterface(columnElm));
+  nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm));
   if (!columnContent->AttrValueIs(kNameSpaceID_None,
                                   nsGkAtoms::editable,
                                   nsGkAtoms::_true,
                                   eCaseMatters))
     return false;
 
-  return mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                            nsGkAtoms::editable,
-                                            nsGkAtoms::_true, eCaseMatters);
+  return mContent->AttrValueIs(kNameSpaceID_None,
+                               nsGkAtoms::editable,
+                               nsGkAtoms::_true, eCaseMatters);
 }
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -365,18 +365,23 @@ ForEachPing(nsIContent* aContent, ForEac
   //       implemented an interface that exposed an enumeration of nsIURIs.
 
   // Make sure we are dealing with either an <A> or <AREA> element in the HTML
   // or XHTML namespace.
   if (!IsElementAnchor(aContent)) {
     return;
   }
 
+  RefPtr<nsAtom> pingAtom = NS_Atomize("ping");
+  if (!pingAtom) {
+    return;
+  }
+
   nsAutoString value;
-  aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::ping, value);
+  aContent->GetAttr(kNameSpaceID_None, pingAtom, value);
   if (value.IsEmpty()) {
     return;
   }
 
   nsCOMPtr<nsIIOService> ios = do_GetIOService();
   if (!ios) {
     return;
   }
@@ -14557,17 +14562,17 @@ nsDocShell::OnLinkClickSync(nsIContent* 
       }
     }
   }
 
   uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
   if (IsElementAnchor(aContent)) {
     MOZ_ASSERT(aContent->IsHTMLElement());
     nsAutoString referrer;
-    aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
+    aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
     nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(referrer);
     while (tok.hasMoreTokens()) {
       const nsAString& token = tok.nextToken();
       if (token.LowerCaseEqualsLiteral("noreferrer")) {
         flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
                  INTERNAL_LOAD_FLAGS_NO_OPENER;
         // We now have all the flags we could possibly have, so just stop.
         break;
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -761,92 +761,32 @@ public:
    * set previously.
    */
   nsresult SetSingleClassFromParser(nsAtom* aSingleClassName);
 
   // 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);
-  /**
-   * 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.
-   * 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;
-
-  /**
-   * Determine if an attribute has been set (empty string or otherwise).
-   *
-   * @param aNameSpaceId the namespace id of the attribute
-   * @param aAttr the attribute name
-   * @return whether an attribute exists
-   */
+  // 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;
-  /**
-   * Test whether this Element's given attribute has the given value.  If the
-   * attribute is not set at all, this will return false.
-   *
-   * @param aNameSpaceID The namespace ID of the attribute.  Must not
-   *                     be kNameSpaceID_Unknown.
-   * @param aName The name atom of the attribute.  Must not be null.
-   * @param aValue The value to compare to.
-   * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
-   */
+  // aCaseSensitive == eIgnoreCaase means ASCII case-insensitive matching.
   inline bool AttrValueIs(int32_t aNameSpaceID, nsAtom* aName,
                           const nsAString& aValue,
                           nsCaseTreatment aCaseSensitive) const;
-
-  /**
-   * Test whether this Element's given attribute has the given value.  If the
-   * attribute is not set at all, this will return false.
-   *
-   * @param aNameSpaceID The namespace ID of the attribute.  Must not
-   *                     be kNameSpaceID_Unknown.
-   * @param aName The name atom of the attribute.  Must not be null.
-   * @param aValue The value to compare to.  Must not be null.
-   * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
-   */
-  bool AttrValueIs(int32_t aNameSpaceID,
-                   nsAtom* aName,
-                   nsAtom* aValue,
-                   nsCaseTreatment aCaseSensitive) const;
-
-  enum {
-    ATTR_MISSING = -1,
-    ATTR_VALUE_NO_MATCH = -2
-  };
-  /**
-   * Check whether this Element's given attribute has one of a given list of
-   * values. If there is a match, we return the index in the list of the first
-   * matching value. If there was no attribute at all, then we return
-   * ATTR_MISSING. If there was an attribute but it didn't match, we return
-   * ATTR_VALUE_NO_MATCH. A non-negative result always indicates a match.
-   *
-   * @param aNameSpaceID The namespace ID of the attribute.  Must not
-   *                     be kNameSpaceID_Unknown.
-   * @param aName The name atom of the attribute.  Must not be null.
-   * @param aValues a nullptr-terminated array of pointers to atom values to test
-   *                against.
-   * @param aCaseSensitive Whether to do a case-sensitive compare on the values.
-   * @return ATTR_MISSING, ATTR_VALUE_NO_MATCH or the non-negative index
-   * indicating the first value of aValues that matched
-   */
-  typedef nsStaticAtom* const* const AttrValuesArray;
+  inline bool AttrValueIs(int32_t aNameSpaceID, nsAtom* aName,
+                          nsAtom* aValue,
+                          nsCaseTreatment aCaseSensitive) const;
   int32_t FindAttrValueIn(int32_t aNameSpaceID,
-                                  nsAtom* aName,
-                                  AttrValuesArray* aValues,
-                                  nsCaseTreatment aCaseSensitive) const;
+                          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.
    *
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -466,21 +466,19 @@ nsIContent::GetBaseURI(bool aTryUseXHRDo
           // XXX Will fail with xml:base
           base = binding->PrototypeBinding()->DocURI();
           break;
         }
       }
     }
 
     // Otherwise check for xml:base attribute
-    if (elem->IsElement()) {
-      elem->AsElement()->GetAttr(kNameSpaceID_XML, nsGkAtoms::base, attr);
-      if (!attr.IsEmpty()) {
-        baseAttrs.AppendElement(attr);
-      }
+    elem->GetAttr(kNameSpaceID_XML, nsGkAtoms::base, attr);
+    if (!attr.IsEmpty()) {
+      baseAttrs.AppendElement(attr);
     }
     elem = elem->GetParent();
   } while(elem);
 
   if (!baseAttrs.IsEmpty()) {
     doc->WarnOnceAbout(nsIDocument::eXMLBaseAttribute);
     // Now resolve against all xml:base attrs
     for (uint32_t i = baseAttrs.Length() - 1; i != uint32_t(-1); --i) {
@@ -1124,16 +1122,53 @@ nsIContent::GetEventTargetParent(EventCh
     }
   } else {
     aVisitor.SetParentTarget(GetComposedDoc(), false);
   }
   return NS_OK;
 }
 
 bool
+nsIContent::GetAttr(int32_t aNameSpaceID, nsAtom* aName,
+                    nsAString& aResult) const
+{
+  if (IsElement()) {
+    return AsElement()->GetAttr(aNameSpaceID, aName, aResult);
+  }
+  aResult.Truncate();
+  return false;
+}
+
+bool
+nsIContent::HasAttr(int32_t aNameSpaceID, nsAtom* aName) const
+{
+  return IsElement() && AsElement()->HasAttr(aNameSpaceID, aName);
+}
+
+bool
+nsIContent::AttrValueIs(int32_t aNameSpaceID,
+                        nsAtom* aName,
+                        const nsAString& aValue,
+                        nsCaseTreatment aCaseSensitive) const
+{
+  return IsElement() &&
+    AsElement()->AttrValueIs(aNameSpaceID, aName, aValue, aCaseSensitive);
+}
+
+bool
+nsIContent::AttrValueIs(int32_t aNameSpaceID,
+                        nsAtom* aName,
+                        nsAtom* aValue,
+                        nsCaseTreatment aCaseSensitive) const
+{
+  return IsElement() &&
+    AsElement()->AttrValueIs(aNameSpaceID, aName, aValue, aCaseSensitive);
+}
+
+bool
 nsIContent::IsFocusable(int32_t* aTabIndex, bool aWithMouse)
 {
   bool focusable = IsFocusableInternal(aTabIndex, aWithMouse);
   // Ensure that the return value and aTabIndex are consistent in the case
   // we're in userfocusignored context.
   if (focusable || (aTabIndex && *aTabIndex != -1)) {
     if (nsContentUtils::IsUserFocusIgnored(this)) {
       if (aTabIndex) {
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -152,19 +152,17 @@ ShadowRoot::AddSlot(HTMLSlotElement* aSl
       currentSlot->EnqueueSlotChangeEvent();
     }
   } else {
     // Otherwise add appropriate nodes to this slot from the host.
     for (nsIContent* child = GetHost()->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
       nsAutoString slotName;
-      if (child->IsElement()) {
-        child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
-      }
+      child->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
       if (child->IsSlotable() && slotName.Equals(name)) {
         currentSlot->AppendAssignedNode(child);
         doEnqueueSlotChange = true;
       }
     }
 
     if (doEnqueueSlotChange) {
       currentSlot->EnqueueSlotChangeEvent();
@@ -347,20 +345,17 @@ ShadowRoot::GetEventTargetParent(EventCh
 }
 
 const HTMLSlotElement*
 ShadowRoot::AssignSlotFor(nsIContent* aContent)
 {
   nsAutoString slotName;
   // Note that if slot attribute is missing, assign it to the first default
   // slot, if exists.
-  if (aContent->IsElement()) {
-    aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
-  }
-
+  aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
   nsTArray<HTMLSlotElement*>* slots = mSlotMap.Get(slotName);
   if (!slots) {
     return nullptr;
   }
 
   HTMLSlotElement* slot = slots->ElementAt(0);
   MOZ_ASSERT(slot);
 
@@ -596,19 +591,17 @@ ShadowRoot::ContentRemoved(nsIDocument* 
   }
 
   if (!aChild->IsSlotable()) {
     return;
   }
 
   if (aContainer && aContainer == GetHost()) {
     nsAutoString slotName;
-    if (aChild->IsElement()) {
-      aChild->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
-    }
+    aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
     if (const HTMLSlotElement* slot = UnassignSlotFor(aChild, slotName)) {
       slot->EnqueueSlotChangeEvent();
     }
     return;
   }
 
   // If parent's root is a shadow root, and parent is a slot whose assigned
   // nodes is the empty list, then run signal a slot change for parent.
--- a/dom/base/nsContentList.cpp
+++ b/dom/base/nsContentList.cpp
@@ -553,20 +553,20 @@ nsContentList::NamedItem(const nsAString
   RefPtr<nsAtom> name = NS_Atomize(aName);
   NS_ENSURE_TRUE(name, nullptr);
 
   for (i = 0; i < count; i++) {
     nsIContent *content = mElements[i];
     // XXX Should this pass eIgnoreCase?
     if (content &&
         ((content->IsHTMLElement() &&
-          content->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
-                                            name, eCaseMatters)) ||
-         content->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id,
-                                           name, eCaseMatters))) {
+          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+                               name, eCaseMatters)) ||
+         content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id,
+                              name, eCaseMatters))) {
       return content->AsElement();
     }
   }
 
   return nullptr;
 }
 
 void
@@ -679,20 +679,18 @@ nsContentList::GetElementAt(uint32_t aIn
 
 nsIContent*
 nsContentList::Item(uint32_t aIndex)
 {
   return GetElementAt(aIndex);
 }
 
 void
-nsContentList::AttributeChanged(nsIDocument* aDocument,
-                                Element* aElement,
-                                int32_t aNameSpaceID,
-                                nsAtom* aAttribute,
+nsContentList::AttributeChanged(nsIDocument *aDocument, Element* aElement,
+                                int32_t aNameSpaceID, nsAtom* aAttribute,
                                 int32_t aModType,
                                 const nsAttrValue* aOldValue)
 {
   NS_PRECONDITION(aElement, "Must have a content node to work with");
 
   if (!mFunc || !mFuncMayDependOnAttr || mState == LIST_DIRTY ||
       !MayContainRelevantNodes(aElement->GetParentNode()) ||
       !nsContentUtils::IsInSameAnonymousTree(mRootNode, aElement)) {
@@ -713,18 +711,17 @@ nsContentList::AttributeChanged(nsIDocum
     // already not there, this is a no-op (though a potentially
     // expensive one).  Either way, no change of mState is required
     // here.
     mElements.RemoveElement(aElement);
   }
 }
 
 void
-nsContentList::ContentAppended(nsIDocument* aDocument,
-                               nsIContent* aContainer,
+nsContentList::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
                                nsIContent* aFirstNewContent)
 {
   NS_PRECONDITION(aContainer, "Can't get at the new content if no container!");
 
   /*
    * If the state is LIST_DIRTY then we have no useful information in our list
    * and we want to put off doing work as much as possible.
    *
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -812,52 +812,49 @@ nsContentSink::ProcessStyleLinkFromHeade
   return NS_OK;
 }
 
 
 nsresult
 nsContentSink::ProcessMETATag(nsIContent* aContent)
 {
   NS_ASSERTION(aContent, "missing meta-element");
-  MOZ_ASSERT(aContent->IsElement());
-
-  Element* element = aContent->AsElement();
 
   nsresult rv = NS_OK;
 
   // set any HTTP-EQUIV data into document's header data as well as url
   nsAutoString header;
-  element->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
+  aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
   if (!header.IsEmpty()) {
     // Ignore META REFRESH when document is sandboxed from automatic features.
     nsContentUtils::ASCIIToLower(header);
     if (nsGkAtoms::refresh->Equals(header) &&
         (mDocument->GetSandboxFlags() & SANDBOXED_AUTOMATIC_FEATURES)) {
       return NS_OK;
     }
 
     // Don't allow setting cookies in <meta http-equiv> in cookie averse
     // documents.
     if (nsGkAtoms::setcookie->Equals(header) && mDocument->IsCookieAverse()) {
       return NS_OK;
     }
 
     nsAutoString result;
-    element->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result);
+    aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result);
     if (!result.IsEmpty()) {
       RefPtr<nsAtom> fieldAtom(NS_Atomize(header));
-      rv = ProcessHeaderData(fieldAtom, result, element);
+      rv = ProcessHeaderData(fieldAtom, result, aContent);
     }
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
-                           nsGkAtoms::handheldFriendly, eIgnoreCase)) {
+  if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+                            nsGkAtoms::handheldFriendly, eIgnoreCase)) {
     nsAutoString result;
-    element->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result);
+    aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result);
     if (!result.IsEmpty()) {
       nsContentUtils::ASCIIToLower(result);
       mDocument->SetHeaderData(nsGkAtoms::handheldFriendly, result);
     }
   }
 
   return rv;
 }
@@ -1077,17 +1074,17 @@ nsContentSink::ProcessOfflineManifest(ns
   // Don't bother processing offline manifest for documents
   // without a docshell
   if (!mDocShell) {
     return;
   }
 
   // Check for a manifest= attribute.
   nsAutoString manifestSpec;
-  aElement->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
+  aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
   ProcessOfflineManifest(manifestSpec);
 }
 
 void
 nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec)
 {
   // Don't bother processing offline manifest for documents
   // without a docshell
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3016,23 +3016,20 @@ static inline void KeyAppendString(const
 
 static inline void KeyAppendInt(int32_t aInt, nsACString& aKey)
 {
   KeyAppendSep(aKey);
 
   aKey.Append(nsPrintfCString("%d", aInt));
 }
 
-static inline bool IsAutocompleteOff(const nsIContent* aContent)
-{
-  return aContent->IsElement() &&
-    aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                       nsGkAtoms::autocomplete,
-                                       NS_LITERAL_STRING("off"),
-                                       eIgnoreCase);
+static inline bool IsAutocompleteOff(const nsIContent* aElement)
+{
+  return aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocomplete,
+                               NS_LITERAL_STRING("off"), eIgnoreCase);
 }
 
 /*static*/ nsresult
 nsContentUtils::GenerateStateKey(nsIContent* aContent,
                                  nsIDocument* aDocument,
                                  nsACString& aKey)
 {
   aKey.Truncate();
@@ -3141,17 +3138,17 @@ nsContentUtils::GenerateStateKey(nsICont
         if (index > -1) {
           KeyAppendInt(index, aKey);
           generatedUniqueKey = true;
         }
       }
 
       // Append the control name
       nsAutoString name;
-      aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
+      aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
       KeyAppendString(name, aKey);
     }
   }
 
   if (!generatedUniqueKey) {
     // Either we didn't have a form control or we aren't in an HTML document so
     // we can't figure out form info.  Append the tag name if it's an element
     // to avoid restoring state for one type of element on another type.
@@ -3821,20 +3818,18 @@ nsContentUtils::ContentIsDraggable(nsICo
 {
   nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aContent);
   if (htmlElement) {
     bool draggable = false;
     htmlElement->GetDraggable(&draggable);
     if (draggable)
       return true;
 
-    if (aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::draggable,
-                                           nsGkAtoms::_false,
-                                           eIgnoreCase))
+    if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
+                              nsGkAtoms::_false, eIgnoreCase))
       return false;
   }
 
   // special handling for content area image and link dragging
   return IsDraggableImage(aContent) || IsDraggableLink(aContent);
 }
 
 // static
@@ -4703,24 +4698,22 @@ nsContentUtils::UnregisterShutdownObserv
     mozilla::services::GetObserverService();
   if (observerService) {
     observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
   }
 }
 
 /* static */
 bool
-nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent,
-                                int32_t aNameSpaceID,
+nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent, int32_t aNameSpaceID,
                                 nsAtom* aName)
 {
-  static Element::AttrValuesArray strings[] = {&nsGkAtoms::_empty, nullptr};
-  return aContent->IsElement() &&
-    aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings, eCaseMatters)
-      == Element::ATTR_VALUE_NO_MATCH;
+  static nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::_empty, nullptr};
+  return aContent->FindAttrValueIn(aNameSpaceID, aName, strings, eCaseMatters)
+    == nsIContent::ATTR_VALUE_NO_MATCH;
 }
 
 /* static */
 bool
 nsContentUtils::HasMutationListeners(nsINode* aNode,
                                      uint32_t aType,
                                      nsINode* aTargetForSubtreeModified)
 {
@@ -5547,17 +5540,17 @@ nsContentUtils::TriggerLink(nsIContent *
     // a pseudo Content-Disposition header.
     // For security reasons we only allow websites to declare same-origin resources
     // as downloadable. If this check fails we will just do the normal thing
     // (i.e. navigate to the resource).
     nsAutoString fileName;
     if ((!aContent->IsHTMLElement(nsGkAtoms::a) &&
          !aContent->IsHTMLElement(nsGkAtoms::area) &&
          !aContent->IsSVGElement(nsGkAtoms::a)) ||
-        !aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::download, fileName) ||
+        !aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::download, fileName) ||
         NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, false, true))) {
       fileName.SetIsVoid(true); // No actionable download attribute was found.
     }
 
     handler->OnLinkClick(aContent, aLinkURI,
                          fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
                          fileName, nullptr, -1, nullptr, aIsTrusted,
                          aContent->NodePrincipal());
@@ -10553,21 +10546,18 @@ nsContentUtils::QueryTriggeringPrincipal
 
   // If aLoadingNode is content, bail out early.
   if (!aLoadingNode->NodePrincipal()->GetIsSystemPrincipal()) {
     loadingPrincipal.forget(aTriggeringPrincipal);
     return result;
   }
 
   nsAutoString loadingStr;
-  if (aLoadingNode->IsElement()) {
-    aLoadingNode->AsElement()->GetAttr(kNameSpaceID_None,
-				       nsGkAtoms::triggeringprincipal,
-				       loadingStr);
-  }
+  aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::triggeringprincipal,
+                        loadingStr);
 
   // Fall back if 'triggeringprincipal' isn't specified,
   if (loadingStr.IsEmpty()) {
     loadingPrincipal.forget(aTriggeringPrincipal);
     return result;
   }
 
   nsCOMPtr<nsISupports> serializedPrincipal;
@@ -10595,21 +10585,18 @@ nsContentUtils::GetContentPolicyTypeForU
 
   bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal);
   if (result) {
     // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
     // indicating it's a favicon loading.
     aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
 
     nsAutoString requestContextID;
-    if (aLoadingNode->IsElement()) {
-      aLoadingNode->AsElement()->GetAttr(kNameSpaceID_None,
-                                         nsGkAtoms::requestcontextid,
-                                         requestContextID);
-    }
+    aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::requestcontextid,
+                          requestContextID);
     nsresult rv;
     int64_t val  = requestContextID.ToInteger64(&rv);
     *aRequestContextID = NS_SUCCEEDED(rv)
       ? val
       : 0;
   } else {
     aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
   }
@@ -11125,26 +11112,19 @@ nsContentUtils::DevToolsEnabled(JSContex
   }
 
   return workerPrivate->DevToolsEnabled();
 }
 
 /* static */ bool
 nsContentUtils::ContentIsLink(nsIContent* aContent)
 {
-  if (!aContent || !aContent->IsElement()) {
-    return false;
-  }
-
-  if (aContent->IsHTMLElement(nsGkAtoms::a)) {
-    return true;
-  }
-
-  return aContent->AsElement()->AttrValueIs(
-      kNameSpaceID_XLink, nsGkAtoms::type, nsGkAtoms::simple, eCaseMatters);
+  return aContent && (aContent->IsHTMLElement(nsGkAtoms::a) ||
+                      aContent->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
+                                            nsGkAtoms::simple, eCaseMatters));
 }
 
 /* static */ already_AddRefed<EventTarget>
 nsContentUtils::TryGetTabChildGlobalAsEventTarget(nsISupports* aFrom)
 {
   nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(aFrom);
   if (!frameLoaderOwner) {
     return nullptr;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -6625,35 +6625,31 @@ nsIDocument::GetBindingParent(nsINode& a
   if (!content)
     return nullptr;
 
   nsIContent* bindingParent = content->GetBindingParent();
   return bindingParent ? bindingParent->AsElement() : nullptr;
 }
 
 static Element*
-GetElementByAttribute(Element* aElement, nsAtom* aAttrName,
+GetElementByAttribute(nsIContent* aContent, nsAtom* aAttrName,
                       const nsAString& aAttrValue, bool aUniversalMatch)
 {
-  if (aUniversalMatch ? aElement->HasAttr(kNameSpaceID_None, aAttrName) :
-                        aElement->AttrValueIs(kNameSpaceID_None, aAttrName,
+  if (aUniversalMatch ? aContent->HasAttr(kNameSpaceID_None, aAttrName) :
+                        aContent->AttrValueIs(kNameSpaceID_None, aAttrName,
                                               aAttrValue, eCaseMatters)) {
-    return aElement;
-  }
-
-  for (nsIContent* child = aElement->GetFirstChild();
+    return aContent->AsElement();
+  }
+
+  for (nsIContent* child = aContent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
-    if (!child->IsElement()) {
-      continue;
-    }
 
     Element* matchedElement =
-      GetElementByAttribute(child->AsElement(), aAttrName, aAttrValue,
-                            aUniversalMatch);
+      GetElementByAttribute(child, aAttrName, aAttrValue, aUniversalMatch);
     if (matchedElement)
       return matchedElement;
   }
 
   return nullptr;
 }
 
 Element*
@@ -6667,23 +6663,18 @@ nsDocument::GetAnonymousElementByAttribu
 
   uint32_t length = 0;
   nodeList->GetLength(&length);
 
   bool universalMatch = aAttrValue.EqualsLiteral("*");
 
   for (uint32_t i = 0; i < length; ++i) {
     nsIContent* current = nodeList->Item(i);
-    if (!current->IsElement()) {
-      continue;
-    }
-
     Element* matchedElm =
-      GetElementByAttribute(current->AsElement(), aAttrName, aAttrValue,
-                            universalMatch);
+      GetElementByAttribute(current, aAttrName, aAttrValue, universalMatch);
     if (matchedElm)
       return matchedElm;
   }
 
   return nullptr;
 }
 
 NS_IMETHODIMP
@@ -10346,20 +10337,20 @@ nsDocument::FindImageMap(const nsAString
   if (!mImageMaps) {
     mImageMaps = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::map, nsGkAtoms::map);
   }
 
   uint32_t i, n = mImageMaps->Length(true);
   nsString name;
   for (i = 0; i < n; ++i) {
     nsIContent* map = mImageMaps->Item(i);
-    if (map->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id, mapName,
-                                      eCaseMatters) ||
-        map->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, mapName,
-                                      eCaseMatters)) {
+    if (map->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id, mapName,
+                         eCaseMatters) ||
+        map->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, mapName,
+                         eCaseMatters)) {
       return map->AsElement();
     }
   }
 
   return nullptr;
 }
 
 #define DEPRECATED_OPERATION(_op) #_op "Warning",
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -2718,20 +2718,20 @@ nsFocusManager::DetermineElementToMoveFo
       // When looking for the first document, if the root wasn't focusable,
       // find the next focusable document.
       aType = MOVEFOCUS_FORWARDDOC;
     } else {
       return NS_OK;
     }
   }
 
-  Element* rootContent = doc->GetRootElement();
+  nsIContent* rootContent = doc->GetRootElement();
   NS_ENSURE_TRUE(rootContent, NS_OK);
 
-  nsIPresShell* presShell = doc->GetShell();
+  nsIPresShell *presShell = doc->GetShell();
   NS_ENSURE_TRUE(presShell, NS_OK);
 
   if (aType == MOVEFOCUS_FIRST) {
     if (!aStartContent)
       startContent = rootContent;
     return GetNextTabbableContent(presShell, startContent,
                                   nullptr, startContent,
                                   true, 1, false, false, aNextContent);
@@ -2779,17 +2779,17 @@ nsFocusManager::DetermineElementToMoveFo
     if (frame) {
       popupFrame =
         nsLayoutUtils::GetClosestFrameOfType(frame, LayoutFrameType::MenuPopup);
     }
 
     if (popupFrame && !forDocumentNavigation) {
       // Don't navigate outside of a popup, so pretend that the
       // root content is the popup itself
-      rootContent = popupFrame->GetContent()->AsElement();
+      rootContent = popupFrame->GetContent();
       NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
     }
     else if (!forward) {
       // If focus moves backward and when current focused node is root
       // content or <body> element which is editable by contenteditable
       // attribute, focus should move to its parent document.
       if (startContent == rootContent) {
         doNavigation = false;
@@ -2817,17 +2817,17 @@ nsFocusManager::DetermineElementToMoveFo
       // at the topmost popup.
       startContent = popupFrame->GetContent();
       NS_ASSERTION(startContent, "Popup frame doesn't have a content node");
       // Unless we are searching for documents, set the root content to the
       // popup as well, so that we don't tab-navigate outside the popup.
       // When navigating by documents, we start at the popup but can navigate
       // outside of it to look for other panels and documents.
       if (!forDocumentNavigation) {
-        rootContent = startContent->AsElement();
+        rootContent = startContent;
       }
 
       doc = startContent ? startContent->GetComposedDoc() : nullptr;
     }
     else {
       // Otherwise, for content shells, start from the location of the caret.
       nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
       if (docShell && docShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
@@ -3002,17 +3002,17 @@ nsFocusManager::DetermineElementToMoveFo
       // popup. This handles the situation of tabbing amongst elements
       // inside an iframe which is itself inside a popup. Otherwise,
       // navigation would move outside the popup when tabbing outside the
       // iframe.
       if (!forDocumentNavigation) {
         popupFrame = nsLayoutUtils::GetClosestFrameOfType(
           frame, LayoutFrameType::MenuPopup);
         if (popupFrame) {
-          rootContent = popupFrame->GetContent()->AsElement();
+          rootContent = popupFrame->GetContent();
           NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
         }
       }
     }
     else {
       // There is no parent, so call the tree owner. This will tell the
       // embedder or parent process that it should take the focus.
       bool tookFocus;
@@ -3035,17 +3035,17 @@ nsFocusManager::DetermineElementToMoveFo
       // continue by looping around to the end again.
       if (forDocumentNavigation && (forward || mayFocusRoot || popupFrame)) {
         // HTML content documents can have their root element focused (a focus
         // ring appears around the entire content area frame). This root
         // appears in the tab order before all of the elements in the document.
         // Chrome documents however cannot be focused directly, so instead we
         // focus the first focusable element within the window.
         // For example, the urlbar.
-        Element* root = GetRootForFocus(piWindow, doc, true, true);
+        nsIContent* root = GetRootForFocus(piWindow, doc, true, true);
         return FocusFirst(root, aNextContent);
       }
 
       // Once we have hit the top-level and have iterated to the end again, we
       // just want to break out next time we hit this spot to prevent infinite
       // iteration.
       mayFocusRoot = true;
 
@@ -3200,22 +3200,22 @@ nsFocusManager::GetNextTabbableContent(n
 
       LOGCONTENTNAVIGATION("Next Tabbable %s:", frame->GetContent());
       LOGFOCUSNAVIGATION(("  with tabindex: %d expected: %d", tabIndex, aCurrentTabIndex));
 
       if (tabIndex >= 0) {
         NS_ASSERTION(currentContent, "IsFocusable set a tabindex for a frame with no content");
         if (!aForDocumentNavigation &&
             currentContent->IsHTMLElement(nsGkAtoms::img) &&
-            currentContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::usemap)) {
+            currentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::usemap)) {
           // This is an image with a map. Image map areas are not traversed by
           // nsIFrameTraversal so look for the next or previous area element.
           nsIContent *areaContent =
             GetNextTabbableMapArea(aForward, aCurrentTabIndex,
-                                   currentContent->AsElement(), iterStartContent);
+                                   currentContent, iterStartContent);
           if (areaContent) {
             NS_ADDREF(*aResultContent = areaContent);
             return NS_OK;
           }
         }
         else if (aIgnoreTabIndex || aCurrentTabIndex == tabIndex) {
           // break out if we've wrapped around to the start again.
           if (aOriginalStartContent && currentContent == aOriginalStartContent) {
@@ -3232,17 +3232,17 @@ nsFocusManager::GetNextTabbableContent(n
           if (remote) {
             remote->NavigateByKey(aForward, aForDocumentNavigation);
             return NS_SUCCESS_DOM_NO_OPERATION;
           }
 
           // Next, for document navigation, check if this a non-remote child document.
           bool checkSubDocument = true;
           if (aForDocumentNavigation) {
-            Element* docRoot = GetRootForChildDocument(currentContent);
+            nsIContent* docRoot = GetRootForChildDocument(currentContent);
             if (docRoot) {
               // If GetRootForChildDocument returned something then call
               // FocusFirst to find the root or first element to focus within
               // the child document. If this is a frameset though, skip this and
               // fall through to the checkSubDocument block below to iterate into
               // the frameset's frames and locate the first focusable frame.
               if (!docRoot->IsHTMLElement(nsGkAtoms::frameset)) {
                 return FocusFirst(docRoot, aResultContent);
@@ -3334,17 +3334,17 @@ nsFocusManager::GetNextTabbableContent(n
     // A bit counterintuitive but true, tabindex order goes 1, 2, ... 32767, 0
     if (aCurrentTabIndex == (aForward ? 0 : 1)) {
       // if going backwards, the canvas should be focused once the beginning
       // has been reached, so get the root element.
       if (!aForward) {
         nsCOMPtr<nsPIDOMWindowOuter> window = GetCurrentWindow(aRootContent);
         NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
-        RefPtr<Element> docRoot =
+        nsCOMPtr<nsIContent> docRoot =
           GetRootForFocus(window, aRootContent->GetComposedDoc(), false, true);
         FocusFirst(docRoot, aResultContent);
       }
       break;
     }
 
     // continue looking for next highest priority tabindex
     aCurrentTabIndex = GetNextTabIndex(aRootContent, aCurrentTabIndex, aForward);
@@ -3352,17 +3352,17 @@ nsFocusManager::GetNextTabbableContent(n
   }
 
   return NS_OK;
 }
 
 nsIContent*
 nsFocusManager::GetNextTabbableMapArea(bool aForward,
                                        int32_t aCurrentTabIndex,
-                                       Element* aImageContent,
+                                       nsIContent* aImageContent,
                                        nsIContent* aStartContent)
 {
   nsAutoString useMap;
   aImageContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, useMap);
 
   nsCOMPtr<nsIDocument> doc = aImageContent->GetComposedDoc();
   if (doc) {
     nsCOMPtr<nsIContent> mapContent = doc->FindImageMap(useMap);
@@ -3407,19 +3407,17 @@ nsFocusManager::GetNextTabIndex(nsIConte
          child;
          child = child->GetNextSibling()) {
       childTabIndex = GetNextTabIndex(child, aCurrentTabIndex, aForward);
       if (childTabIndex > aCurrentTabIndex && childTabIndex != tabIndex) {
         tabIndex = (tabIndex == 0 || childTabIndex < tabIndex) ? childTabIndex : tabIndex;
       }
 
       nsAutoString tabIndexStr;
-      if (child->IsElement()) {
-        child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr);
-      }
+      child->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr);
       nsresult ec;
       int32_t val = tabIndexStr.ToInteger(&ec);
       if (NS_SUCCEEDED (ec) && val > aCurrentTabIndex && val != tabIndex) {
         tabIndex = (tabIndex == 0 || val < tabIndex) ? val : tabIndex;
       }
     }
   }
   else { /* !aForward */
@@ -3429,49 +3427,47 @@ nsFocusManager::GetNextTabIndex(nsIConte
          child = child->GetNextSibling()) {
       childTabIndex = GetNextTabIndex(child, aCurrentTabIndex, aForward);
       if ((aCurrentTabIndex == 0 && childTabIndex > tabIndex) ||
           (childTabIndex < aCurrentTabIndex && childTabIndex > tabIndex)) {
         tabIndex = childTabIndex;
       }
 
       nsAutoString tabIndexStr;
-      if (child->IsElement()) {
-        child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr);
-      }
+      child->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr);
       nsresult ec;
       int32_t val = tabIndexStr.ToInteger(&ec);
       if (NS_SUCCEEDED (ec)) {
         if ((aCurrentTabIndex == 0 && val > tabIndex) ||
             (val < aCurrentTabIndex && val > tabIndex) ) {
           tabIndex = val;
         }
       }
     }
   }
 
   return tabIndex;
 }
 
 nsresult
-nsFocusManager::FocusFirst(Element* aRootElement, nsIContent** aNextContent)
+nsFocusManager::FocusFirst(nsIContent* aRootContent, nsIContent** aNextContent)
 {
-  if (!aRootElement) {
+  if (!aRootContent) {
     return NS_OK;
   }
 
-  nsIDocument* doc = aRootElement->GetComposedDoc();
+  nsIDocument* doc = aRootContent->GetComposedDoc();
   if (doc) {
     if (doc->IsXULDocument()) {
       // If the redirectdocumentfocus attribute is set, redirect the focus to a
       // specific element. This is primarily used to retarget the focus to the
       // urlbar during document navigation.
       nsAutoString retarget;
 
-      if (aRootElement->GetAttr(kNameSpaceID_None,
+      if (aRootContent->GetAttr(kNameSpaceID_None,
                                nsGkAtoms::retargetdocumentfocus, retarget)) {
         nsCOMPtr<Element> element = doc->GetElementById(retarget);
         nsCOMPtr<nsIContent> retargetElement =
           CheckIfFocusable(element, 0);
         if (retargetElement) {
           retargetElement.forget(aNextContent);
           return NS_OK;
         }
@@ -3480,29 +3476,29 @@ nsFocusManager::FocusFirst(Element* aRoo
 
     nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
     if (docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
       // If the found content is in a chrome shell, navigate forward one
       // tabbable item so that the first item is focused. Note that we
       // always go forward and not back here.
       nsIPresShell* presShell = doc->GetShell();
       if (presShell) {
-        return GetNextTabbableContent(presShell, aRootElement,
-                                      nullptr, aRootElement,
+        return GetNextTabbableContent(presShell, aRootContent,
+                                      nullptr, aRootContent,
                                       true, 1, false, false,
                                       aNextContent);
       }
     }
   }
 
-  NS_ADDREF(*aNextContent = aRootElement);
+  NS_ADDREF(*aNextContent = aRootContent);
   return NS_OK;
 }
 
-Element*
+nsIContent*
 nsFocusManager::GetRootForFocus(nsPIDOMWindowOuter* aWindow,
                                 nsIDocument* aDocument,
                                 bool aForDocumentNavigation,
                                 bool aCheckVisibility)
 {
   if (!aForDocumentNavigation) {
     nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
     if (docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
@@ -3510,44 +3506,44 @@ nsFocusManager::GetRootForFocus(nsPIDOMW
     }
   }
 
   if (aCheckVisibility && !IsWindowVisible(aWindow))
     return nullptr;
 
   // If the body is contenteditable, use the editor's root element rather than
   // the actual root element.
-  RefPtr<Element> rootElement =
+  nsCOMPtr<nsIContent> rootElement =
     nsLayoutUtils::GetEditableRootContentByContentEditable(aDocument);
   if (!rootElement || !rootElement->GetPrimaryFrame()) {
     rootElement = aDocument->GetRootElement();
     if (!rootElement) {
       return nullptr;
     }
   }
 
   if (aCheckVisibility && !rootElement->GetPrimaryFrame()) {
     return nullptr;
   }
 
   // Finally, check if this is a frameset
   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDocument);
   if (htmlDoc) {
-    Element* htmlChild = aDocument->GetHtmlChildElement(nsGkAtoms::frameset);
+    nsIContent* htmlChild = aDocument->GetHtmlChildElement(nsGkAtoms::frameset);
     if (htmlChild) {
       // In document navigation mode, return the frameset so that navigation
       // descends into the child frames.
       return aForDocumentNavigation ? htmlChild : nullptr;
     }
   }
 
   return rootElement;
 }
 
-Element*
+nsIContent*
 nsFocusManager::GetRootForChildDocument(nsIContent* aContent)
 {
   // Check for elements that represent child documents, that is, browsers,
   // editors or frames from a frameset. We don't include iframes since we
   // consider them to be an integral part of the same window or page.
   if (!aContent ||
       !(aContent->IsXULElement(nsGkAtoms::browser) ||
         aContent->IsXULElement(nsGkAtoms::editor) ||
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -484,54 +484,54 @@ protected:
    * aCurrentTabIndex is the current tabindex.
    *
    * aImageContent is the image.
    *
    * aStartContent is the current image map area.
    */
   nsIContent* GetNextTabbableMapArea(bool aForward,
                                      int32_t aCurrentTabIndex,
-                                     mozilla::dom::Element* aImageContent,
+                                     nsIContent* aImageContent,
                                      nsIContent* aStartContent);
 
   /**
    * Return the next valid tabindex value after aCurrentTabIndex, if aForward
    * is true, or the previous tabindex value if aForward is false. aParent is
    * the node from which to start looking for tab indicies.
    */
   int32_t GetNextTabIndex(nsIContent* aParent,
                           int32_t aCurrentTabIndex,
                           bool aForward);
 
   /**
    * Focus the first focusable content within the document with a root node of
    * aRootContent. For content documents, this will be aRootContent itself, but
    * for chrome documents, this will locate the next focusable content.
    */
-  nsresult FocusFirst(mozilla::dom::Element* aRootContent, nsIContent** aNextContent);
+  nsresult FocusFirst(nsIContent* aRootContent, nsIContent** aNextContent);
 
   /**
    * Retrieves and returns the root node from aDocument to be focused. Will
    * return null if the root node cannot be focused. There are several reasons
    * for this:
    *
    * - if aForDocumentNavigation is false and aWindow is a chrome shell.
    * - if aCheckVisibility is true and the aWindow is not visible.
    * - if aDocument is a frameset document.
    */
-  mozilla::dom::Element* GetRootForFocus(nsPIDOMWindowOuter* aWindow,
-                                         nsIDocument* aDocument,
-                                         bool aForDocumentNavigation,
-                                         bool aCheckVisibility);
+  nsIContent* GetRootForFocus(nsPIDOMWindowOuter* aWindow,
+                              nsIDocument* aDocument,
+                              bool aForDocumentNavigation,
+                              bool aCheckVisibility);
 
   /**
    * Retrieves and returns the root node as with GetRootForFocus but only if
    * aContent is a frame with a valid child document.
    */
-  mozilla::dom::Element* GetRootForChildDocument(nsIContent* aContent);
+  nsIContent* GetRootForChildDocument(nsIContent* aContent);
 
   /**
    * Retreives a focusable element within the current selection of aWindow.
    * Currently, this only detects links.
    *
    * This is used when MoveFocus is called with a type of MOVEFOCUS_CARET,
    * which is used, for example, to focus links as the caret is moved over
    * them.
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -351,16 +351,100 @@ public:
 
   bool IsGeneratedContentContainerForAfter() const
   {
     return IsRootOfNativeAnonymousSubtree() &&
            mNodeInfo->NameAtom() == nsGkAtoms::mozgeneratedcontentafter;
   }
 
   /**
+   * 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
+   * @param aAttr the attribute name
+   * @return whether an attribute exists
+   */
+  bool HasAttr(int32_t aNameSpaceID, nsAtom* aName) const;
+
+  /**
+   * Test whether this content node's given attribute has the given value.  If
+   * the attribute is not set at all, this will return false.
+   *
+   * @param aNameSpaceID The namespace ID of the attribute.  Must not
+   *                     be kNameSpaceID_Unknown.
+   * @param aName The name atom of the attribute.  Must not be null.
+   * @param aValue The value to compare to.
+   * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
+   */
+  bool AttrValueIs(int32_t aNameSpaceID,
+                   nsAtom* aName,
+                   const nsAString& aValue,
+                   nsCaseTreatment aCaseSensitive) const;
+
+  /**
+   * Test whether this content node's given attribute has the given value.  If
+   * the attribute is not set at all, this will return false.
+   *
+   * @param aNameSpaceID The namespace ID of the attribute.  Must not
+   *                     be kNameSpaceID_Unknown.
+   * @param aName The name atom of the attribute.  Must not be null.
+   * @param aValue The value to compare to.  Must not be null.
+   * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
+   */
+  bool AttrValueIs(int32_t aNameSpaceID,
+                   nsAtom* aName,
+                   nsAtom* aValue,
+                   nsCaseTreatment aCaseSensitive) const;
+
+  enum {
+    ATTR_MISSING = -1,
+    ATTR_VALUE_NO_MATCH = -2
+  };
+  /**
+   * Check whether this content node's given attribute has one of a given
+   * list of values. If there is a match, we return the index in the list
+   * of the first matching value. If there was no attribute at all, then
+   * we return ATTR_MISSING. If there was an attribute but it didn't
+   * match, we return ATTR_VALUE_NO_MATCH. A non-negative result always
+   * indicates a match.
+   *
+   * @param aNameSpaceID The namespace ID of the attribute.  Must not
+   *                     be kNameSpaceID_Unknown.
+   * @param aName The name atom of the attribute.  Must not be null.
+   * @param aValues a nullptr-terminated array of pointers to atom values to test
+   *                against.
+   * @param aCaseSensitive Whether to do a case-sensitive compare on the values.
+   * @return ATTR_MISSING, ATTR_VALUE_NO_MATCH or the non-negative index
+   * indicating the first value of aValues that matched
+   */
+  typedef nsStaticAtom* const* const AttrValuesArray;
+  virtual int32_t FindAttrValueIn(int32_t aNameSpaceID,
+                                  nsAtom* aName,
+                                  AttrValuesArray* aValues,
+                                  nsCaseTreatment aCaseSensitive) const
+  {
+    return ATTR_MISSING;
+  }
+
+  /**
    * 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.
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -615,20 +615,20 @@ nsObjectLoadingContent::BindToTree(nsIDo
   return NS_OK;
 }
 
 void
 nsObjectLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
 
-  nsCOMPtr<Element> thisElement =
+  nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
-  MOZ_ASSERT(thisElement);
-  nsIDocument* ownerDoc = thisElement->OwnerDoc();
+  MOZ_ASSERT(thisContent);
+  nsIDocument* ownerDoc = thisContent->OwnerDoc();
   ownerDoc->RemovePlugin(this);
 
   /// XXX(johns): Do we want to somehow propogate the reparenting behavior to
   ///             FakePlugin types as well?
   if (mType == eType_Plugin && (mInstanceOwner || mInstantiating)) {
     // we'll let the plugin continue to run at least until we get back to
     // the event loop. If we get back to the event loop and the node
     // has still not been added back to the document then we tear down the
@@ -637,17 +637,17 @@ nsObjectLoadingContent::UnbindFromTree(b
   } else if (mType != eType_Image) {
     // nsImageLoadingContent handles the image case.
     // Reset state and clear pending events
     /// XXX(johns): The implementation for GenericFrame notes that ideally we
     ///             would keep the docshell around, but trash the frameloader
     UnloadObject();
   }
   if (mType == eType_Plugin) {
-    nsIDocument* doc = thisElement->GetComposedDoc();
+    nsIDocument* doc = thisContent->GetComposedDoc();
     if (doc && doc->IsActive()) {
       nsCOMPtr<nsIRunnable> ev = new nsSimplePluginEvent(doc,
                                                          NS_LITERAL_STRING("PluginRemoved"));
       NS_DispatchToCurrentThread(ev);
     }
   }
 }
 
@@ -1552,19 +1552,19 @@ nsObjectLoadingContent::CheckProcessPoli
   }
 
   return true;
 }
 
 nsObjectLoadingContent::ParameterUpdateFlags
 nsObjectLoadingContent::UpdateObjectParameters()
 {
-  nsCOMPtr<Element> thisElement =
+  nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
-  MOZ_ASSERT(thisElement, "Must be an Element");
+  NS_ASSERTION(thisContent, "Must be an instance of content");
 
   uint32_t caps = GetCapabilities();
   LOG(("OBJLC [%p]: Updating object parameters", this));
 
   nsresult rv;
   nsAutoCString newMime;
   nsAutoString typeAttr;
   nsCOMPtr<nsIURI> newURI;
@@ -1588,66 +1588,69 @@ nsObjectLoadingContent::UpdateObjectPara
   ///
   /// Initial MIME Type
   ///
   ///
   /// Codebase
   ///
 
   nsAutoString codebaseStr;
-  nsCOMPtr<nsIURI> docBaseURI = thisElement->GetBaseURI();
-  thisElement->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase, codebaseStr);
+  nsCOMPtr<nsIURI> docBaseURI = thisContent->GetBaseURI();
+  bool hasCodebase = thisContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase);
+  if (hasCodebase) {
+    thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase, codebaseStr);
+  }
 
   if (!codebaseStr.IsEmpty()) {
     rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(newBaseURI),
                                                    codebaseStr,
-                                                   thisElement->OwnerDoc(),
+                                                   thisContent->OwnerDoc(),
                                                    docBaseURI);
     if (NS_SUCCEEDED(rv)) {
       NS_TryToSetImmutable(newBaseURI);
     } else {
       // Malformed URI
       LOG(("OBJLC [%p]: Could not parse plugin's codebase as a URI, "
            "will use document baseURI instead", this));
     }
   }
 
   nsAutoString rawTypeAttr;
-  thisElement->GetAttr(kNameSpaceID_None, nsGkAtoms::type, rawTypeAttr);
+  thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, rawTypeAttr);
   if (!rawTypeAttr.IsEmpty()) {
     typeAttr = rawTypeAttr;
     CopyUTF16toUTF8(rawTypeAttr, newMime);
   }
 
   // If we failed to build a valid URI, use the document's base URI
   if (!newBaseURI) {
     newBaseURI = docBaseURI;
   }
 
   ///
   /// URI
   ///
 
   nsAutoString uriStr;
   // Different elements keep this in various locations
-  if (thisElement->NodeInfo()->Equals(nsGkAtoms::object)) {
-    thisElement->GetAttr(kNameSpaceID_None, nsGkAtoms::data, uriStr);
-  } else if (thisElement->NodeInfo()->Equals(nsGkAtoms::embed)) {
-    thisElement->GetAttr(kNameSpaceID_None, nsGkAtoms::src, uriStr);
+  if (thisContent->NodeInfo()->Equals(nsGkAtoms::object)) {
+    thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, uriStr);
+  } else if (thisContent->NodeInfo()->Equals(nsGkAtoms::embed)) {
+    thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, uriStr);
   } else {
     NS_NOTREACHED("Unrecognized plugin-loading tag");
   }
 
   mRewrittenYoutubeEmbed = false;
   // Note that the baseURI changing could affect the newURI, even if uriStr did
   // not change.
   if (!uriStr.IsEmpty()) {
     rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(newURI),
                                                    uriStr,
-                                                   thisElement->OwnerDoc(),
+                                                   thisContent->OwnerDoc(),
                                                    newBaseURI);
     nsCOMPtr<nsIURI> rewrittenURI;
     MaybeRewriteYoutubeEmbed(newURI,
                              newBaseURI,
                              getter_AddRefs(rewrittenURI));
     if (rewrittenURI) {
       newURI = rewrittenURI;
       mRewrittenYoutubeEmbed = true;
@@ -1739,17 +1742,17 @@ nsObjectLoadingContent::UpdateObjectPara
     // 3) If we have eAllowPluginSkipChannel, use the uri file extension if
     //    it matches a plugin
     // 4) If the channel returns a binary stream type:
     //    4a) If we have a type non-null non-document type hint, use that
     //    4b) If the uri file extension matches a plugin type, use that
     // 5) Use the channel type
 
     bool overrideChannelType = false;
-    if (thisElement->HasAttr(kNameSpaceID_None, nsGkAtoms::typemustmatch)) {
+    if (thisContent->HasAttr(kNameSpaceID_None, nsGkAtoms::typemustmatch)) {
       if (!typeAttr.LowerCaseEqualsASCII(channelType.get())) {
         stateInvalid = true;
       }
     } else if (IsPluginType(typeHint)) {
       LOG(("OBJLC [%p]: Using plugin type hint in favor of any channel type",
            this));
       overrideChannelType = true;
     } else if ((caps & eAllowPluginSkipChannel) &&
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -348,17 +348,17 @@ nsStyleLinkElement::UpdateStyleSheetInte
 static bool
 IsScopedStyleElement(nsIContent* aContent)
 {
   // This is quicker than, say, QIing aContent to nsStyleLinkElement
   // and then calling its virtual GetStyleSheetInfo method to find out
   // if it is scoped.
   return (aContent->IsHTMLElement(nsGkAtoms::style) ||
           aContent->IsSVGElement(nsGkAtoms::style)) &&
-         aContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::scoped) &&
+         aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scoped) &&
          aContent->OwnerDoc()->IsScopedStyleEnabled();
 }
 
 static bool
 HasScopedStyleSheetChild(nsIContent* aContent)
 {
   for (nsIContent* n = aContent->GetFirstChild(); n; n = n->GetNextSibling()) {
     if (IsScopedStyleElement(n)) {
@@ -533,35 +533,32 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
   if (isInline) {
     nsAutoString text;
     if (!nsContentUtils::GetNodeTextContent(thisContent, false, text, fallible)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     MOZ_ASSERT(thisContent->NodeInfo()->NameAtom() != nsGkAtoms::link,
                "<link> is not 'inline', and needs different CSP checks");
-    MOZ_ASSERT(thisContent->IsElement());
-    if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent->AsElement(),
+    if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent,
                                            thisContent->NodePrincipal(),
                                            triggeringPrincipal,
                                            doc->GetDocumentURI(),
                                            mLineNumber, text, &rv))
       return rv;
 
     // Parse the style sheet.
     rv = doc->CSSLoader()->
       LoadInlineStyle(thisContent, text, triggeringPrincipal, mLineNumber,
                       title, media, referrerPolicy, scopeElement,
                       aObserver, &doneLoading, &isAlternate);
-  } else {
+  }
+  else {
     nsAutoString integrity;
-    if (thisContent->IsElement()) {
-      thisContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::integrity,
-                                        integrity);
-    }
+    thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::integrity, integrity);
     if (!integrity.IsEmpty()) {
       MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
               ("nsStyleLinkElement::DoUpdateStyleSheet, integrity=%s",
                NS_ConvertUTF16toUTF8(integrity).get()));
     }
 
     // XXXbz clone the URI here to work around content policies modifying URIs.
     nsCOMPtr<nsIURI> clonedURI;
--- a/dom/base/nsTextNode.cpp
+++ b/dom/base/nsTextNode.cpp
@@ -83,17 +83,17 @@ private:
 
   // Update our text to our parent's current attr value
   void UpdateText(bool aNotify);
 
   // This doesn't need to be a strong pointer because it's only non-null
   // while we're bound to the document tree, and it points to an ancestor
   // so the ancestor must be bound to the document tree the whole time
   // and can't be deleted.
-  Element* mGrandparent;
+  nsIContent* mGrandparent;
   // What attribute we're showing
   int32_t mNameSpaceID;
   RefPtr<nsAtom> mAttrName;
 };
 
 nsTextNode::~nsTextNode()
 {
 }
@@ -244,17 +244,17 @@ nsAttributeTextNode::BindToTree(nsIDocum
   NS_PRECONDITION(aParent && aParent->GetParent(),
                   "This node can't be a child of the document or of the document root");
 
   nsresult rv = nsTextNode::BindToTree(aDocument, aParent,
                                        aBindingParent, aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ASSERTION(!mGrandparent, "We were already bound!");
-  mGrandparent = aParent->GetParent()->AsElement();
+  mGrandparent = aParent->GetParent();
   mGrandparent->AddMutationObserver(this);
 
   // Note that there is no need to notify here, since we have no
   // frame yet at this point.
   UpdateText(false);
 
   return NS_OK;
 }
--- a/dom/base/nsXHTMLContentSerializer.cpp
+++ b/dom/base/nsXHTMLContentSerializer.cpp
@@ -353,19 +353,19 @@ nsXHTMLContentSerializer::AfterElementSt
     // Check if there already are any content-type meta children.
     // If there are, they will be modified to use the correct charset.
     // If there aren't, we'll insert one here.
     bool hasMeta = false;
     for (nsIContent* child = aContent->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
       if (child->IsHTMLElement(nsGkAtoms::meta) &&
-          child->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::content)) {
+          child->HasAttr(kNameSpaceID_None, nsGkAtoms::content)) {
         nsAutoString header;
-        child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
+        child->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
 
         if (header.LowerCaseEqualsLiteral("content-type")) {
           hasMeta = true;
           break;
         }
       }
     }
 
--- a/dom/base/nsXMLContentSerializer.cpp
+++ b/dom/base/nsXMLContentSerializer.cpp
@@ -1289,35 +1289,35 @@ nsXMLContentSerializer::MaybeFlagNewline
     mAddNewlineForRootNode = parent->IsNodeOfType(nsINode::eDOCUMENT);
   }
 }
 
 void
 nsXMLContentSerializer::MaybeEnterInPreContent(nsIContent* aNode)
 {
   // support of the xml:space attribute
-  nsAutoString space;
   if (ShouldMaintainPreLevel() &&
-      aNode->IsElement() &&
-      aNode->AsElement()->GetAttr(kNameSpaceID_XML, nsGkAtoms::space, space) &&
-      space.EqualsLiteral("preserve")) {
-    ++PreLevel();
+      aNode->HasAttr(kNameSpaceID_XML, nsGkAtoms::space)) {
+    nsAutoString space;
+    aNode->GetAttr(kNameSpaceID_XML, nsGkAtoms::space, space);
+    if (space.EqualsLiteral("preserve"))
+      ++PreLevel();
   }
 }
 
 void
 nsXMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
 {
   // support of the xml:space attribute
-  nsAutoString space;
   if (ShouldMaintainPreLevel() &&
-      aNode->IsElement() &&
-      aNode->AsElement()->GetAttr(kNameSpaceID_XML, nsGkAtoms::space, space) &&
-      space.EqualsLiteral("preserve")) {
-    --PreLevel();
+      aNode->HasAttr(kNameSpaceID_XML, nsGkAtoms::space)) {
+    nsAutoString space;
+    aNode->GetAttr(kNameSpaceID_XML, nsGkAtoms::space, space);
+    if (space.EqualsLiteral("preserve"))
+      --PreLevel();
   }
 }
 
 bool
 nsXMLContentSerializer::AppendNewLineToString(nsAString& aStr)
 {
   bool result = AppendToString(mLineBreak, aStr);
   mMayIgnoreLineBreakSequence = true;
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -541,24 +541,24 @@ ContentEventHandler::QueryContentRect(ns
 
 // Editor places a bogus BR node under its root content if the editor doesn't
 // have any text. This happens even for single line editors.
 // When we get text content and when we change the selection,
 // we don't want to include the bogus BRs at the end.
 static bool IsContentBR(nsIContent* aContent)
 {
   return aContent->IsHTMLElement(nsGkAtoms::br) &&
-         !aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                             nsGkAtoms::type,
-                                             nsGkAtoms::moz,
-                                             eIgnoreCase) &&
-         !aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                             nsGkAtoms::mozeditorbogusnode,
-                                             nsGkAtoms::_true,
-                                             eIgnoreCase);
+         !aContent->AttrValueIs(kNameSpaceID_None,
+                                nsGkAtoms::type,
+                                nsGkAtoms::moz,
+                                eIgnoreCase) &&
+         !aContent->AttrValueIs(kNameSpaceID_None,
+                                nsGkAtoms::mozeditorbogusnode,
+                                nsGkAtoms::_true,
+                                eIgnoreCase);
 }
 
 static bool IsMozBR(nsIContent* aContent)
 {
   return aContent->IsHTMLElement(nsGkAtoms::br) && !IsContentBR(aContent);
 }
 
 static void ConvertToNativeNewlines(nsString& aString)
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -992,18 +992,17 @@ GetAccessKeyTypeFor(nsISupports* aDocShe
 }
 
 static bool
 IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsAString& aKey)
 {
   // Use GetAttr because we want Unicode case=insensitive matching
   // XXXbz shouldn't this be case-sensitive, per spec?
   nsString contentKey;
-  if (!aContent->IsElement() ||
-      !aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, contentKey) ||
+  if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, contentKey) ||
       !contentKey.Equals(aKey, nsCaseInsensitiveStringComparator()))
     return false;
 
   nsCOMPtr<nsIDOMXULDocument> xulDoc =
     do_QueryInterface(aContent->OwnerDoc());
   if (!xulDoc && !aContent->IsXULElement())
     return true;
 
@@ -1597,22 +1596,19 @@ EventStateManager::FireContextClick()
     } else if (mGestureDownContent->IsXULElement(nsGkAtoms::toolbarbutton)) {
       // a <toolbarbutton> that has the container attribute set
       // will already have its own dropdown.
       if (nsContentUtils::HasNonEmptyAttr(mGestureDownContent,
               kNameSpaceID_None, nsGkAtoms::container)) {
         allowedToDispatch = false;
       } else {
         // If the toolbar button has an open menu, don't attempt to open
-        // a second menu
-        if (mGestureDownContent->IsElement() &&
-            mGestureDownContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                          nsGkAtoms::open,
-                                                          nsGkAtoms::_true,
-                                                          eCaseMatters)) {
+          // a second menu
+        if (mGestureDownContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::open,
+                                             nsGkAtoms::_true, eCaseMatters)) {
           allowedToDispatch = false;
         }
       }
     }
     else if (mGestureDownContent->IsHTMLElement()) {
       nsCOMPtr<nsIFormControl> formCtrl(do_QueryInterface(mGestureDownContent));
 
       if (formCtrl) {
@@ -2952,17 +2948,17 @@ EventStateManager::DecideGestureEvent(Wi
 
 #ifdef XP_MACOSX
 static bool
 NodeAllowsClickThrough(nsINode* aNode)
 {
   while (aNode) {
     if (aNode->IsXULElement()) {
       mozilla::dom::Element* element = aNode->AsElement();
-      static Element::AttrValuesArray strings[] =
+      static nsIContent::AttrValuesArray strings[] =
         {&nsGkAtoms::always, &nsGkAtoms::never, nullptr};
       switch (element->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::clickthrough,
                                        strings, eCaseMatters)) {
         case 0:
           return true;
         case 1:
           return false;
       }
@@ -5320,39 +5316,39 @@ EventStateManager::EventStatusOK(WidgetG
            aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
            !sNormalLMouseEventInProcess);
 }
 
 //-------------------------------------------
 // Access Key Registration
 //-------------------------------------------
 void
-EventStateManager::RegisterAccessKey(Element* aElement, uint32_t aKey)
+EventStateManager::RegisterAccessKey(nsIContent* aContent, uint32_t aKey)
 {
-  if (aElement && mAccessKeys.IndexOf(aElement) == -1)
-    mAccessKeys.AppendObject(aElement);
+  if (aContent && mAccessKeys.IndexOf(aContent) == -1)
+    mAccessKeys.AppendObject(aContent);
 }
 
 void
-EventStateManager::UnregisterAccessKey(Element* aElement, uint32_t aKey)
+EventStateManager::UnregisterAccessKey(nsIContent* aContent, uint32_t aKey)
 {
-  if (aElement)
-    mAccessKeys.RemoveObject(aElement);
+  if (aContent)
+    mAccessKeys.RemoveObject(aContent);
 }
 
 uint32_t
-EventStateManager::GetRegisteredAccessKey(Element* aElement)
+EventStateManager::GetRegisteredAccessKey(nsIContent* aContent)
 {
-  MOZ_ASSERT(aElement);
-
-  if (mAccessKeys.IndexOf(aElement) == -1)
+  MOZ_ASSERT(aContent);
+
+  if (mAccessKeys.IndexOf(aContent) == -1)
     return 0;
 
   nsAutoString accessKey;
-  aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
+  aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
   return accessKey.First();
 }
 
 void
 EventStateManager::EnsureDocument(nsPresContext* aPresContext)
 {
   if (!mDocument)
     mDocument = aPresContext->Document();
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -159,36 +159,36 @@ public:
    * asynchronously.
    */
   void TryToFlushPendingNotificationsToIME();
 
   /**
    * Register accesskey on the given element. When accesskey is activated then
    * the element will be notified via nsIContent::PerformAccesskey() method.
    *
-   * @param  aElement  the given element
+   * @param  aContent  the given element
    * @param  aKey      accesskey
    */
-  void RegisterAccessKey(dom::Element* aElement, uint32_t aKey);
+  void RegisterAccessKey(nsIContent* aContent, uint32_t aKey);
 
   /**
    * Unregister accesskey for the given element.
    *
-   * @param  aElement  the given element
+   * @param  aContent  the given element
    * @param  aKey      accesskey
    */
-  void UnregisterAccessKey(dom::Element* aElement, uint32_t aKey);
+  void UnregisterAccessKey(nsIContent* aContent, uint32_t aKey);
 
   /**
    * Get accesskey registered on the given element or 0 if there is none.
    *
-   * @param  aElement  the given element (must not be null)
+   * @param  aContent  the given element (must not be null)
    * @return           registered accesskey
    */
-  uint32_t GetRegisteredAccessKey(dom::Element* aContent);
+  uint32_t GetRegisteredAccessKey(nsIContent* aContent);
 
   static void GetAccessKeyLabelPrefix(dom::Element* aElement, nsAString& aPrefix);
 
   /**
    * HandleAccessKey() looks for access keys which matches with aEvent and
    * execute when it matches with a chrome access key or some content access
    * keys.
    * If the event may match chrome access keys, this handles the access key
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -1288,46 +1288,45 @@ IMEStateManager::SetIMEState(const IMESt
 
   if (aContent &&
       aContent->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
     if (!aContent->IsHTMLElement(nsGkAtoms::textarea)) {
       // <input type=number> has an anonymous <input type=text> descendant
       // that gets focus whenever anyone tries to focus the number control. We
       // need to check if aContent is one of those anonymous text controls and,
       // if so, use the number control instead:
-      Element* element = aContent->AsElement();
+      nsIContent* content = aContent;
       HTMLInputElement* inputElement =
         HTMLInputElement::FromContentOrNull(aContent);
       if (inputElement) {
         HTMLInputElement* ownerNumberControl =
           inputElement->GetOwnerNumberControl();
         if (ownerNumberControl) {
-          element = ownerNumberControl; // an <input type=number>
+          content = ownerNumberControl; // an <input type=number>
         }
       }
-      element->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
+      content->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
                        context.mHTMLInputType);
     } else {
       context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String());
     }
 
     if (sInputModeSupported ||
         nsContentUtils::IsChromeDoc(aContent->OwnerDoc())) {
-      aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::inputmode,
-                                     context.mHTMLInputInputmode);
+      aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::inputmode,
+                        context.mHTMLInputInputmode);
       if (context.mHTMLInputInputmode.EqualsLiteral("mozAwesomebar") &&
           !nsContentUtils::IsChromeDoc(aContent->OwnerDoc())) {
         // mozAwesomebar should be allowed only in chrome
         context.mHTMLInputInputmode.Truncate();
       }
     }
 
-    aContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                   nsGkAtoms::moz_action_hint,
-                                   context.mActionHint);
+    aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
+                      context.mActionHint);
 
     // Get the input content corresponding to the focused node,
     // which may be an anonymous child of the input content.
     nsIContent* inputContent = aContent->FindFirstNonChromeOnlyAccessContent();
 
     // If we don't have an action hint and
     // return won't submit the form, use "next".
     if (context.mActionHint.IsEmpty() &&
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -690,17 +690,17 @@ HTMLFormElement::BuildSubmission(HTMLFor
 
   return NS_OK;
 }
 
 nsresult
 HTMLFormElement::SubmitSubmission(HTMLFormSubmission* aFormSubmission)
 {
   nsresult rv;
-  Element* originatingElement = aFormSubmission->GetOriginatingElement();
+  nsIContent* originatingElement = aFormSubmission->GetOriginatingElement();
 
   //
   // Get the action and target
   //
   nsCOMPtr<nsIURI> actionURI;
   rv = GetActionURL(getter_AddRefs(actionURI), originatingElement);
   NS_ENSURE_SUBMIT_SUCCESS(rv);
 
@@ -1540,17 +1540,17 @@ HTMLFormElement::DoResolveName(const nsA
                                bool aFlushContent)
 {
   nsCOMPtr<nsISupports> result =
     mControls->NamedItemInternal(aName, aFlushContent);
   return result.forget();
 }
 
 void
-HTMLFormElement::OnSubmitClickBegin(Element* aOriginatingElement)
+HTMLFormElement::OnSubmitClickBegin(nsIContent* aOriginatingElement)
 {
   mDeferSubmission = true;
 
   // Prepare to run NotifySubmitObservers early before the
   // scripts on the page get to modify the form data, possibly
   // throwing off any password manager. (bug 257781)
   nsCOMPtr<nsIURI> actionURI;
   nsresult rv;
@@ -1608,17 +1608,17 @@ HTMLFormElement::GetAction(nsString& aVa
     }
   } else {
     GetURIAttr(nsGkAtoms::action, nullptr, aValue);
   }
 }
 
 nsresult
 HTMLFormElement::GetActionURL(nsIURI** aActionURL,
-                              Element* aOriginatingElement)
+                              nsIContent* aOriginatingElement)
 {
   nsresult rv = NS_OK;
 
   *aActionURL = nullptr;
 
   //
   // Grab the URL string
   //
@@ -2257,19 +2257,19 @@ HTMLFormElement::WalkRadioGroup(const ns
     // XXX If the name is empty, it's not stored in the control list.  There
     // *must* be a more efficient way to do this.
     //
     nsCOMPtr<nsIFormControl> control;
     uint32_t len = GetElementCount();
     for (uint32_t i = 0; i < len; i++) {
       control = GetElementAt(i);
       if (control->ControlType() == NS_FORM_INPUT_RADIO) {
-        nsCOMPtr<Element> controlElement = do_QueryInterface(control);
-        if (controlElement &&
-            controlElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+        nsCOMPtr<nsIContent> controlContent = do_QueryInterface(control);
+        if (controlContent &&
+            controlContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
                                         EmptyString(), eCaseMatters) &&
             !aVisitor->Visit(control)) {
           break;
         }
       }
     }
     return NS_OK;
   }
@@ -2456,18 +2456,17 @@ HTMLFormElement::AddElementToTableIntern
       }
 
       // Found an element, create a list, add the element to the list and put
       // the list in the hash
       RadioNodeList *list = new RadioNodeList(this);
 
       // If an element has a @form, we can assume it *might* be able to not have
       // a parent and still be in the form.
-      NS_ASSERTION((content->IsElement() &&
-                    content->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) ||
+      NS_ASSERTION(content->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
                    content->GetParent(), "Item in list without parent");
 
       // Determine the ordering between the new and old element.
       bool newFirst = nsContentUtils::PositionIsBefore(aChild, content);
 
       list->AppendElement(newFirst ? aChild : content.get());
       list->AppendElement(newFirst ? content.get() : aChild);
 
--- a/dom/html/HTMLFormElement.h
+++ b/dom/html/HTMLFormElement.h
@@ -237,17 +237,17 @@ public:
    */
   bool IsDefaultSubmitElement(const nsIFormControl* aControl) const;
 
   /**
    * Flag the form to know that a button or image triggered scripted form
    * submission. In that case the form will defer the submission until the
    * script handler returns and the return value is known.
    */
-  void OnSubmitClickBegin(Element* aOriginatingElement);
+  void OnSubmitClickBegin(nsIContent* aOriginatingElement);
   void OnSubmitClickEnd();
 
   /**
    * This method will update the form validity so the submit controls states
    * will be updated (for -moz-submit-invalid pseudo-class).
    * This method has to be called by form elements whenever their validity state
    * or status regarding constraint validation changes.
    *
@@ -515,17 +515,17 @@ protected:
   already_AddRefed<nsISupports> DoResolveName(const nsAString& aName, bool aFlushContent);
 
   /**
    * Get the full URL to submit to.  Do not submit if the returned URL is null.
    *
    * @param aActionURL the full, unadulterated URL you'll be submitting to [OUT]
    * @param aOriginatingElement the originating element of the form submission [IN]
    */
-  nsresult GetActionURL(nsIURI** aActionURL, Element* aOriginatingElement);
+  nsresult GetActionURL(nsIURI** aActionURL, nsIContent* aOriginatingElement);
 
   /**
    * Check the form validity following this algorithm:
    * http://www.whatwg.org/specs/web-apps/current-work/#statically-validate-the-constraints
    *
    * @param aInvalidElements [out] parameter containing the list of unhandled
    * invalid controls.
    *
--- a/dom/html/HTMLFormSubmission.cpp
+++ b/dom/html/HTMLFormSubmission.cpp
@@ -89,17 +89,17 @@ public:
   /**
    * @param aEncoding the character encoding of the form
    * @param aMethod the method of the submit (either NS_FORM_METHOD_GET or
    *        NS_FORM_METHOD_POST).
    */
   FSURLEncoded(NotNull<const Encoding*> aEncoding,
                int32_t aMethod,
                nsIDocument* aDocument,
-               Element* aOriginatingElement)
+               nsIContent* aOriginatingElement)
     : EncodingFormSubmission(aEncoding, aOriginatingElement)
     , mMethod(aMethod)
     , mDocument(aDocument)
     , mWarnedFileControl(false)
   {
   }
 
   virtual nsresult
@@ -391,17 +391,17 @@ FSURLEncoded::URLEncode(const nsAString&
   return NS_OK;
 }
 
 } // anonymous namespace
 
 // --------------------------------------------------------------------------
 
 FSMultipartFormData::FSMultipartFormData(NotNull<const Encoding*> aEncoding,
-                                         Element* aOriginatingElement)
+                                         nsIContent* aOriginatingElement)
   : EncodingFormSubmission(aEncoding, aOriginatingElement)
 {
   mPostData =
     do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
 
   nsCOMPtr<nsIInputStream> inputStream = do_QueryInterface(mPostData);
   MOZ_ASSERT(SameCOMIdentity(mPostData, inputStream));
   mPostDataStream = inputStream;
@@ -665,17 +665,17 @@ FSMultipartFormData::AddPostDataStream()
 // --------------------------------------------------------------------------
 
 namespace {
 
 class FSTextPlain : public EncodingFormSubmission
 {
 public:
   FSTextPlain(NotNull<const Encoding*> aEncoding,
-              Element* aOriginatingElement)
+              nsIContent* aOriginatingElement)
     : EncodingFormSubmission(aEncoding, aOriginatingElement)
   {
   }
 
   virtual nsresult
   AddNameValuePair(const nsAString& aName, const nsAString& aValue) override;
 
   virtual nsresult
@@ -791,17 +791,17 @@ FSTextPlain::GetEncodedSubmission(nsIURI
 }
 
 } // anonymous namespace
 
 // --------------------------------------------------------------------------
 
 EncodingFormSubmission::EncodingFormSubmission(
   NotNull<const Encoding*> aEncoding,
-  Element* aOriginatingElement)
+  nsIContent* aOriginatingElement)
   : HTMLFormSubmission(aEncoding, aOriginatingElement)
 {
   if (!aEncoding->CanEncodeEverything()) {
     nsAutoCString name;
     aEncoding->Name(name);
     NS_ConvertUTF8toUTF16 nameUtf16(name);
     const char16_t* namePtr = nameUtf16.get();
     SendJSWarning(aOriginatingElement ? aOriginatingElement->GetOwnerDocument()
--- a/dom/html/HTMLFormSubmission.h
+++ b/dom/html/HTMLFormSubmission.h
@@ -3,18 +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_HTMLFormSubmission_h
 #define mozilla_dom_HTMLFormSubmission_h
 
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/Element.h"
 #include "nsCOMPtr.h"
+#include "nsIContent.h"
 #include "mozilla/Encoding.h"
 #include "nsString.h"
 
 class nsIURI;
 class nsIInputStream;
 class nsGenericHTMLElement;
 class nsIMultiplexInputStream;
 
@@ -90,48 +90,48 @@ public:
   GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
                        int64_t* aPostDataStreamLength) = 0;
 
   /**
    * Get the charset that will be used for submission.
    */
   void GetCharset(nsACString& aCharset) { mEncoding->Name(aCharset); }
 
-  Element* GetOriginatingElement() const
+  nsIContent* GetOriginatingElement() const
   {
     return mOriginatingElement.get();
   }
 
 protected:
   /**
    * Can only be constructed by subclasses.
    *
    * @param aEncoding the character encoding of the form
    * @param aOriginatingElement the originating element (can be null)
    */
   HTMLFormSubmission(mozilla::NotNull<const mozilla::Encoding*> aEncoding,
-                     Element* aOriginatingElement)
+                     nsIContent* aOriginatingElement)
     : mEncoding(aEncoding)
     , mOriginatingElement(aOriginatingElement)
   {
     MOZ_COUNT_CTOR(HTMLFormSubmission);
   }
 
   // The character encoding of this form submission
   mozilla::NotNull<const mozilla::Encoding*> mEncoding;
 
   // Originating element.
-  RefPtr<Element> mOriginatingElement;
+  nsCOMPtr<nsIContent> mOriginatingElement;
 };
 
 class EncodingFormSubmission : public HTMLFormSubmission
 {
 public:
   EncodingFormSubmission(mozilla::NotNull<const mozilla::Encoding*> aEncoding,
-                         Element* aOriginatingElement);
+                         nsIContent* aOriginatingElement);
 
   virtual ~EncodingFormSubmission();
 
   /**
    * Encode a Unicode string to bytes using the encoder (or just copy the input
    * if there is no encoder).
    * @param aStr the string to encode
    * @param aResult the encoded string [OUT]
@@ -149,17 +149,17 @@ public:
  */
 class FSMultipartFormData : public EncodingFormSubmission
 {
 public:
   /**
    * @param aEncoding the character encoding of the form
    */
   FSMultipartFormData(mozilla::NotNull<const mozilla::Encoding*> aEncoding,
-                      Element* aOriginatingElement);
+                      nsIContent* aOriginatingElement);
   ~FSMultipartFormData();
 
   virtual nsresult
   AddNameValuePair(const nsAString& aName, const nsAString& aValue) override;
 
   virtual nsresult
   AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob) override;
 
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -1140,40 +1140,40 @@ HTMLImageElement::UpdateResponsiveSource
       // that and keep it if it's still usable.
       bool changed = mResponsiveSelector->SelectImage(true);
       if (mResponsiveSelector->NumCandidates()) {
         bool isUsableCandidate = true;
 
         // an otherwise-usable source element may still have a media query that may not
         // match any more.
         if (candidateSource->IsHTMLElement(nsGkAtoms::source) &&
-            !SourceElementMatches(candidateSource->AsElement())) {
+            !SourceElementMatches(candidateSource->AsContent())) {
           isUsableCandidate = false;
         }
 
         if (isUsableCandidate) {
           return changed;
         }
       }
 
       // no longer valid
       mResponsiveSelector = nullptr;
       if (candidateSource == this) {
         // No further possibilities
         break;
       }
     } else if (candidateSource == this) {
       // We are the last possible source
-      if (!TryCreateResponsiveSelector(candidateSource->AsElement())) {
+      if (!TryCreateResponsiveSelector(candidateSource->AsContent())) {
         // Failed to find any source
         mResponsiveSelector = nullptr;
       }
       break;
     } else if (candidateSource->IsHTMLElement(nsGkAtoms::source) &&
-               TryCreateResponsiveSelector(candidateSource->AsElement())) {
+               TryCreateResponsiveSelector(candidateSource->AsContent())) {
       // This led to a valid source, stop
       break;
     }
     candidateSource = candidateSource->GetNextSibling();
   }
 
   if (!candidateSource) {
     // Ran out of siblings without finding ourself, e.g. XBL magic.
@@ -1200,84 +1200,83 @@ HTMLImageElement::SupportedPictureSource
   }
 
   return
     imgLoader::SupportImageWithMimeType(NS_ConvertUTF16toUTF8(type).get(),
                                         AcceptedMimeTypes::IMAGES_AND_DOCUMENTS);
 }
 
 bool
-HTMLImageElement::SourceElementMatches(Element* aSourceElement)
+HTMLImageElement::SourceElementMatches(nsIContent* aSourceNode)
 {
-  MOZ_ASSERT(aSourceElement->IsHTMLElement(nsGkAtoms::source));
+  MOZ_ASSERT(aSourceNode->IsHTMLElement(nsGkAtoms::source));
 
   DebugOnly<Element *> parent(nsINode::GetParentElement());
   MOZ_ASSERT(parent && parent->IsHTMLElement(nsGkAtoms::picture));
-  MOZ_ASSERT(IsPreviousSibling(aSourceElement, this));
+  MOZ_ASSERT(IsPreviousSibling(aSourceNode, this));
 
   // Check media and type
-  auto* src = static_cast<HTMLSourceElement*>(aSourceElement);
+  HTMLSourceElement *src = static_cast<HTMLSourceElement*>(aSourceNode);
   if (!src->MatchesCurrentMedia()) {
     return false;
   }
 
   nsAutoString type;
-  if (src->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
+  if (aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
       !SupportedPictureSourceType(type)) {
     return false;
   }
 
   return true;
 }
 
 bool
-HTMLImageElement::TryCreateResponsiveSelector(Element* aSourceElement)
+HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode)
 {
   nsCOMPtr<nsIPrincipal> principal;
 
   // Skip if this is not a <source> with matching media query
-  bool isSourceTag = aSourceElement->IsHTMLElement(nsGkAtoms::source);
+  bool isSourceTag = aSourceNode->IsHTMLElement(nsGkAtoms::source);
   if (isSourceTag) {
-    if (!SourceElementMatches(aSourceElement)) {
+    if (!SourceElementMatches(aSourceNode)) {
       return false;
     }
-    auto* source = HTMLSourceElement::FromContent(aSourceElement);
+    auto* source = HTMLSourceElement::FromContent(aSourceNode);
     principal = source->GetSrcsetTriggeringPrincipal();
-  } else if (aSourceElement->IsHTMLElement(nsGkAtoms::img)) {
+  } else if (aSourceNode->IsHTMLElement(nsGkAtoms::img)) {
     // Otherwise this is the <img> tag itself
-    MOZ_ASSERT(aSourceElement == this);
+    MOZ_ASSERT(aSourceNode == this);
     principal = mSrcsetTriggeringPrincipal;
   }
 
   // Skip if has no srcset or an empty srcset
   nsString srcset;
-  if (!aSourceElement->GetAttr(kNameSpaceID_None, nsGkAtoms::srcset, srcset)) {
+  if (!aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::srcset, srcset)) {
     return false;
   }
 
   if (srcset.IsEmpty()) {
     return false;
   }
 
 
   // Try to parse
-  RefPtr<ResponsiveImageSelector> sel =
-    new ResponsiveImageSelector(aSourceElement);
+  RefPtr<ResponsiveImageSelector> sel = new ResponsiveImageSelector(aSourceNode);
   if (!sel->SetCandidatesFromSourceSet(srcset, principal)) {
     // No possible candidates, don't need to bother parsing sizes
     return false;
   }
 
   nsAutoString sizes;
-  aSourceElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sizes, sizes);
+  aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::sizes, sizes);
   sel->SetSizesFromDescriptor(sizes);
 
   // If this is the <img> tag, also pull in src as the default source
   if (!isSourceTag) {
-    MOZ_ASSERT(aSourceElement == this);
+    MOZ_ASSERT(aSourceNode == this);
     nsAutoString src;
     if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src) && !src.IsEmpty()) {
       sel->SetDefaultSource(src, mSrcTriggeringPrincipal);
     }
   }
 
   mResponsiveSelector = sel;
   return true;
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -365,17 +365,17 @@ protected:
   bool UpdateResponsiveSource();
 
   // Given a <source> node that is a previous sibling *or* ourselves, try to
   // create a ResponsiveSelector.
 
   // If the node's srcset/sizes make for an invalid selector, returns
   // false. This does not guarantee the resulting selector matches an image,
   // only that it is valid.
-  bool TryCreateResponsiveSelector(Element* aSourceElement);
+  bool TryCreateResponsiveSelector(nsIContent *aSourceNode);
 
   MOZ_CAN_RUN_SCRIPT CSSIntPoint GetXY();
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
   void UpdateFormOwner();
 
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
@@ -395,17 +395,17 @@ protected:
   // This is a weak reference that this element and the HTMLFormElement
   // cooperate in maintaining.
   HTMLFormElement* mForm;
 
   // Created when we're tracking responsive image state
   RefPtr<ResponsiveImageSelector> mResponsiveSelector;
 
 private:
-  bool SourceElementMatches(Element* aSourceElement);
+  bool SourceElementMatches(nsIContent* aSourceNode);
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     GenericSpecifiedValues* aGenericData);
   /**
    * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
    * It will not be called if the value is being unset.
    *
    * @param aNamespaceID the namespace of the attr being set
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -4130,17 +4130,17 @@ HTMLInputElement::ShouldPreventDOMActiva
    *  - the event was targeted to our button which should have sent a
    *    DOMActivate event.
    */
 
   if (mType != NS_FORM_INPUT_FILE) {
     return false;
   }
 
-  nsCOMPtr<Element> target = do_QueryInterface(aOriginalTarget);
+  nsCOMPtr<nsIContent> target = do_QueryInterface(aOriginalTarget);
   if (!target) {
     return false;
   }
 
   return target->GetParent() == this &&
          target->IsRootOfNativeAnonymousSubtree() &&
          target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                              nsGkAtoms::button, eCaseMatters);
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -229,17 +229,17 @@ HTMLLinkElement::CreateAndDispatchEvent(
     return;
 
   // In the unlikely case that both rev is specified *and* rel=stylesheet,
   // this code will cause the event to fire, on the principle that maybe the
   // page really does want to specify that its author is a stylesheet. Since
   // this should never actually happen and the performance hit is minimal,
   // doing the "right" thing costs virtually nothing here, even if it doesn't
   // make much sense.
-  static Element::AttrValuesArray strings[] =
+  static nsIContent::AttrValuesArray strings[] =
     {&nsGkAtoms::_empty, &nsGkAtoms::stylesheet, nullptr};
 
   if (!nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
                                        nsGkAtoms::rev) &&
       FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::rel,
                       strings, eIgnoreCase) != ATTR_VALUE_NO_MATCH)
     return;
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2356,17 +2356,17 @@ void HTMLMediaElement::LoadFromSourceChi
   NS_ASSERTION(mDelayingLoadEvent,
                "Should delay load event (if in document) during load");
   NS_ASSERTION(mIsLoadingFromSourceChildren,
                "Must remember we're loading from source children");
 
   AddMutationObserverUnlessExists(this);
 
   while (true) {
-    Element* child = GetNextSource();
+    nsIContent* child = GetNextSource();
     if (!child) {
       // Exhausted candidates, wait for more candidates to be appended to
       // the media element.
       mLoadWaitStatus = WAITING_FOR_SOURCE;
       ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE);
       ChangeDelayLoadStatus(false);
       ReportLoadError("MediaLoadExhaustedCandidates");
       return;
@@ -6764,18 +6764,17 @@ void HTMLMediaElement::NotifyAddedSource
   if (mLoadWaitStatus == WAITING_FOR_SOURCE) {
     // Rest the flag so we don't queue multiple LoadFromSourceTask() when
     // multiple <source> are attached in an event loop.
     mLoadWaitStatus = NOT_WAITING;
     QueueLoadFromSourceTask();
   }
 }
 
-Element*
-HTMLMediaElement::GetNextSource()
+nsIContent* HTMLMediaElement::GetNextSource()
 {
   mSourceLoadCandidate = nullptr;
 
   while (true) {
     if (mSourcePointer == nsINode::GetLastChild()) {
       return nullptr; // no more children
     }
 
@@ -6784,17 +6783,17 @@ HTMLMediaElement::GetNextSource()
     } else {
       mSourcePointer = mSourcePointer->GetNextSibling();
     }
     nsIContent* child = mSourcePointer;
 
     // If child is a <source> element, it is the next candidate.
     if (child && child->IsHTMLElement(nsGkAtoms::source)) {
       mSourceLoadCandidate = child;
-      return child->AsElement();
+      return child;
     }
   }
   NS_NOTREACHED("Execution should not reach here!");
   return nullptr;
 }
 
 void HTMLMediaElement::ChangeDelayLoadStatus(bool aDelay)
 {
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1065,17 +1065,17 @@ protected:
    */
   MediaResult LoadResource();
 
   /**
    * Selects the next <source> child from which to load a resource. Called
    * during the resource selection algorithm. Stores the return value in
    * mSourceLoadCandidate before returning.
    */
-  Element* GetNextSource();
+  nsIContent* GetNextSource();
 
   /**
    * Changes mDelayingLoadEvent, and will call BlockOnLoad()/UnblockOnLoad()
    * on the owning document, so it can delay the load event firing.
    */
   void ChangeDelayLoadStatus(bool aDelay);
 
   /**
--- a/dom/html/HTMLMenuElement.cpp
+++ b/dom/html/HTMLMenuElement.cpp
@@ -210,19 +210,19 @@ HTMLMenuElement::TraverseContent(nsICont
       menuitem->GetIcon(icon);
 
       aBuilder->AddItemFor(menuitem, CanLoadIcon(child, icon));
 
       aSeparator = ST_FALSE;
     } else if (child->IsHTMLElement(nsGkAtoms::hr)) {
       aBuilder->AddSeparator();
     } else if (child->IsHTMLElement(nsGkAtoms::menu) && !element->IsHidden()) {
-      if (child->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::label)) {
+      if (child->HasAttr(kNameSpaceID_None, nsGkAtoms::label)) {
         nsAutoString label;
-        child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label, label);
+        child->GetAttr(kNameSpaceID_None, nsGkAtoms::label, label);
 
         BuildSubmenu(label, child, aBuilder);
 
         aSeparator = ST_FALSE;
       } else {
         AddSeparator(aBuilder, aSeparator);
 
         TraverseContent(child, aBuilder, aSeparator);
--- a/dom/html/HTMLSharedElement.cpp
+++ b/dom/html/HTMLSharedElement.cpp
@@ -122,25 +122,25 @@ HTMLSharedElement::IsAttributeMapped(con
 static void
 SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
 {
   NS_PRECONDITION(aDocument, "Need a document!");
 
   for (nsIContent* child = aDocument->GetFirstChild(); child;
        child = child->GetNextNode()) {
     if (child->IsHTMLElement(nsGkAtoms::base) &&
-        child->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
+        child->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
       if (aMustMatch && child != aMustMatch) {
         return;
       }
 
       // Resolve the <base> element's href relative to our document's
       // fallback base URI.
       nsAutoString href;
-      child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
+      child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
 
       nsCOMPtr<nsIURI> newBaseURI;
       nsContentUtils::NewURIWithDocumentCharset(
         getter_AddRefs(newBaseURI), href, aDocument,
         aDocument->GetFallbackBaseURI());
 
       // Check if CSP allows this base-uri
       nsCOMPtr<nsIContentSecurityPolicy> csp;
@@ -175,23 +175,23 @@ static void
 SetBaseTargetUsingFirstBaseWithTarget(nsIDocument* aDocument,
                                       nsIContent* aMustMatch)
 {
   NS_PRECONDITION(aDocument, "Need a document!");
 
   for (nsIContent* child = aDocument->GetFirstChild(); child;
        child = child->GetNextNode()) {
     if (child->IsHTMLElement(nsGkAtoms::base) &&
-        child->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
+        child->HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
       if (aMustMatch && child != aMustMatch) {
         return;
       }
 
       nsString target;
-      child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::target, target);
+      child->GetAttr(kNameSpaceID_None, nsGkAtoms::target, target);
       aDocument->SetBaseTarget(target);
       return;
     }
   }
 
   aDocument->SetBaseTarget(EmptyString());
 }
 
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -242,20 +242,20 @@ Element*
 TableRowsCollection::GetFirstNamedElement(const nsAString& aName, bool& aFound)
 {
   EnsureInitialized();
   aFound = false;
   RefPtr<nsAtom> nameAtom = NS_Atomize(aName);
   NS_ENSURE_TRUE(nameAtom, nullptr);
 
   for (auto& node : mRows) {
-    if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
-                                       nameAtom, eCaseMatters) ||
-        node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id,
-                                       nameAtom, eCaseMatters)) {
+    if (node->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+                          nameAtom, eCaseMatters) ||
+        node->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id,
+                          nameAtom, eCaseMatters)) {
       aFound = true;
       return node->AsElement();
     }
   }
 
   return nullptr;
 }
 
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -376,21 +376,20 @@ nsGenericHTMLElement::GetOffsetRect(CSSI
 
 bool
 nsGenericHTMLElement::Spellcheck()
 {
   // Has the state has been explicitly set?
   nsIContent* node;
   for (node = this; node; node = node->GetParent()) {
     if (node->IsHTMLElement()) {
-      static Element::AttrValuesArray strings[] =
+      static nsIContent::AttrValuesArray strings[] =
         {&nsGkAtoms::_true, &nsGkAtoms::_false, nullptr};
-      switch (node->AsElement()->FindAttrValueIn(kNameSpaceID_None,
-                                                 nsGkAtoms::spellcheck, strings,
-                                                 eCaseMatters)) {
+      switch (node->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::spellcheck,
+                                    strings, eCaseMatters)) {
         case 0:                         // spellcheck = "true"
           return true;
         case 1:                         // spellcheck = "false"
           return false;
       }
     }
   }
 
@@ -2782,19 +2781,17 @@ MakeContentDescendantsEditable(nsIConten
 
   Element *element = aContent->AsElement();
 
   element->UpdateEditableState(true);
 
   for (nsIContent *child = aContent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
-    if (!child->IsElement() ||
-        !child->AsElement()->HasAttr(kNameSpaceID_None,
-                                     nsGkAtoms::contenteditable)) {
+    if (!child->HasAttr(kNameSpaceID_None, nsGkAtoms::contenteditable)) {
       MakeContentDescendantsEditable(child, aDocument);
     }
   }
 }
 
 void
 nsGenericHTMLElement::ChangeEditableState(int32_t aChange)
 {
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -958,17 +958,17 @@ protected:
   /**
    * Returns eTrue if the element has a contentEditable attribute and its value
    * is "true" or an empty string. Returns eFalse if the element has a
    * contentEditable attribute and its value is "false". Otherwise returns
    * eInherit.
    */
   ContentEditableTristate GetContentEditableValue() const
   {
-    static const Element::AttrValuesArray values[] =
+    static const nsIContent::AttrValuesArray values[] =
       { &nsGkAtoms::_false, &nsGkAtoms::_true, &nsGkAtoms::_empty, nullptr };
 
     if (!MayHaveContentEditableAttr())
       return eInherit;
 
     int32_t value = FindAttrValueIn(kNameSpaceID_None,
                                     nsGkAtoms::contenteditable, values,
                                     eIgnoreCase);
--- a/dom/html/nsIConstraintValidation.cpp
+++ b/dom/html/nsIConstraintValidation.cpp
@@ -57,21 +57,21 @@ nsIConstraintValidation::GetValidity(nsI
 
 void
 nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage,
                                               ErrorResult& aError)
 {
   aValidationMessage.Truncate();
 
   if (IsCandidateForConstraintValidation() && !IsValid()) {
-    nsCOMPtr<Element> element = do_QueryInterface(this);
-    NS_ASSERTION(element, "This class should be inherited by HTML elements only!");
+    nsCOMPtr<nsIContent> content = do_QueryInterface(this);
+    NS_ASSERTION(content, "This class should be inherited by HTML elements only!");
 
     nsAutoString authorMessage;
-    element->GetAttr(kNameSpaceID_None, nsGkAtoms::x_moz_errormessage,
+    content->GetAttr(kNameSpaceID_None, nsGkAtoms::x_moz_errormessage,
                      authorMessage);
 
     if (!authorMessage.IsEmpty()) {
       aValidationMessage.Assign(authorMessage);
       if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) {
         aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage);
       }
     } else if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
@@ -182,17 +182,19 @@ nsIConstraintValidation::ReportValidity(
 
     if (observer) {
       observer->NotifyInvalidSubmit(nullptr, invalidElements);
     }
   }
 
   if (content->IsHTMLElement(nsGkAtoms::input) &&
       nsContentUtils::IsFocusedContent(content)) {
-    HTMLInputElement* inputElement = HTMLInputElement::FromContent(content);
+    HTMLInputElement* inputElement =
+    HTMLInputElement::FromContentOrNull(content);
+
     inputElement->UpdateValidityUIBits(true);
   }
 
   dom::Element* element = content->AsElement();
   element->UpdateState(true);
   return false;
 }
 
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -201,22 +201,21 @@ nsITextControlElement::GetWrapPropertyEn
   // soft is the default; "physical" defaults to soft as well because all other
   // browsers treat it that way and there is no real reason to maintain physical
   // and virtual as separate entities if no one else does.  Only hard and off
   // do anything different.
   aWrapProp = eHTMLTextWrap_Soft; // the default
 
   nsAutoString wrap;
   if (aContent->IsHTMLElement()) {
-    static Element::AttrValuesArray strings[] =
+    static nsIContent::AttrValuesArray strings[] =
       {&nsGkAtoms::HARD, &nsGkAtoms::OFF, nullptr};
 
-    switch (aContent->AsElement()->FindAttrValueIn(kNameSpaceID_None,
-                                                   nsGkAtoms::wrap, strings,
-                                                   eIgnoreCase)) {
+    switch (aContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::wrap,
+                                      strings, eIgnoreCase)) {
       case 0: aWrapProp = eHTMLTextWrap_Hard; break;
       case 1: aWrapProp = eHTMLTextWrap_Off; break;
     }
 
     return true;
   }
 
   return false;
@@ -1551,26 +1550,27 @@ nsTextEditorState::PrepareEditor(const n
   if (shouldInitializeEditor) {
     // Set up wrapping
     newTextEditor->SetWrapColumn(GetWrapCols());
   }
 
   // Set max text field length
   newTextEditor->SetMaxTextLength(GetMaxLength());
 
-  if (nsCOMPtr<Element> element = do_QueryInterface(mTextCtrlElement)) {
+  nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
+  if (content) {
     editorFlags = newTextEditor->Flags();
 
     // Check if the readonly attribute is set.
-    if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly))
+    if (content->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly))
       editorFlags |= nsIPlaintextEditor::eEditorReadonlyMask;
 
     // Check if the disabled attribute is set.
     // TODO: call IsDisabled() here!
-    if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled))
+    if (content->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled))
       editorFlags |= nsIPlaintextEditor::eEditorDisabledMask;
 
     // Disable the selection if necessary.
     if (newTextEditor->IsDisabled()) {
       mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_OFF);
     }
 
     newTextEditor->SetFlags(editorFlags);
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -1006,38 +1006,38 @@ nsMathMLElement::IsLink(nsIURI** aURI) c
     //   xlink:href    - must be set
     //   xlink:type    - must be unset or set to "" or set to "simple"
     //   xlink:show    - must be unset or set to "", "new" or "replace"
     //   xlink:actuate - must be unset or set to "" or "onRequest"
     //
     // For any other values, we're either not a *clickable* XLink, or the end
     // result is poorly specified. Either way, we return false.
 
-    static Element::AttrValuesArray sTypeVals[] =
+    static nsIContent::AttrValuesArray sTypeVals[] =
       { &nsGkAtoms::_empty, &nsGkAtoms::simple, nullptr };
 
-    static Element::AttrValuesArray sShowVals[] =
+    static nsIContent::AttrValuesArray sShowVals[] =
       { &nsGkAtoms::_empty, &nsGkAtoms::_new, &nsGkAtoms::replace, nullptr };
 
-    static Element::AttrValuesArray sActuateVals[] =
+    static nsIContent::AttrValuesArray sActuateVals[] =
       { &nsGkAtoms::_empty, &nsGkAtoms::onRequest, nullptr };
 
     // Optimization: check for href first for early return
     href = mAttrsAndChildren.GetAttr(nsGkAtoms::href,
                                      kNameSpaceID_XLink);
     if (href &&
         FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::type,
                         sTypeVals, eCaseMatters) !=
-        Element::ATTR_VALUE_NO_MATCH &&
+        nsIContent::ATTR_VALUE_NO_MATCH &&
         FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
                         sShowVals, eCaseMatters) !=
-        Element::ATTR_VALUE_NO_MATCH &&
+        nsIContent::ATTR_VALUE_NO_MATCH &&
         FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::actuate,
                         sActuateVals, eCaseMatters) !=
-        Element::ATTR_VALUE_NO_MATCH) {
+        nsIContent::ATTR_VALUE_NO_MATCH) {
       hasHref = true;
     }
   }
 
   if (hasHref) {
     nsCOMPtr<nsIURI> baseURI = GetBaseURI();
     // Get absolute URI
     nsAutoString hrefStr;
@@ -1058,17 +1058,17 @@ nsMathMLElement::GetLinkTarget(nsAString
   const nsAttrValue* target = mAttrsAndChildren.GetAttr(nsGkAtoms::target,
                                                         kNameSpaceID_XLink);
   if (target) {
     target->ToString(aTarget);
   }
 
   if (aTarget.IsEmpty()) {
 
-    static Element::AttrValuesArray sShowVals[] =
+    static nsIContent::AttrValuesArray sShowVals[] =
       { &nsGkAtoms::_new, &nsGkAtoms::replace, nullptr };
 
     switch (FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
                             sShowVals, eCaseMatters)) {
     case 0:
       aTarget.AssignLiteral("_blank");
       return;
     case 1:
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -250,22 +250,18 @@ IsScriptEventHandler(ScriptKind kind, ns
     return false;
   }
 
   if (!aScriptElement->IsHTMLElement()) {
     return false;
   }
 
   nsAutoString forAttr, eventAttr;
-  if (!aScriptElement->AsElement()->GetAttr(kNameSpaceID_None,
-                                            nsGkAtoms::_for,
-                                            forAttr) ||
-      !aScriptElement->AsElement()->GetAttr(kNameSpaceID_None,
-                                            nsGkAtoms::event,
-                                            eventAttr)) {
+  if (!aScriptElement->GetAttr(kNameSpaceID_None, nsGkAtoms::_for, forAttr) ||
+      !aScriptElement->GetAttr(kNameSpaceID_None, nsGkAtoms::event, eventAttr)) {
     return false;
   }
 
   const nsAString& for_str =
     nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(forAttr);
   if (!for_str.LowerCaseEqualsLiteral("window")) {
     return true;
   }
@@ -1247,17 +1243,17 @@ CSPAllowsInlineScript(nsIScriptElement* 
   NS_ENSURE_SUCCESS(rv, false);
 
   if (!csp) {
     // no CSP --> allow
     return true;
   }
 
   // query the nonce
-  nsCOMPtr<Element> scriptContent = do_QueryInterface(aElement);
+  nsCOMPtr<nsIContent> scriptContent = do_QueryInterface(aElement);
   nsAutoString nonce;
   scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce);
   bool parserCreated = aElement->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER;
 
   bool allowInlineScript = false;
   rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
                             nonce, parserCreated, aElement,
                             aElement->GetScriptLineNumber(),
@@ -1327,36 +1323,34 @@ ScriptLoader::ProcessScriptElement(nsISc
     if (!type.IsEmpty()) {
       NS_ENSURE_TRUE(ParseTypeAttribute(type, &validJSVersion), false);
     } else if (!hasType) {
       // no 'type=' element
       // "language" is a deprecated attribute of HTML, so we check it only for
       // HTML script elements.
       if (scriptContent->IsHTMLElement()) {
         nsAutoString language;
-        scriptContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                            nsGkAtoms::language,
-                                            language);
+        scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::language, language);
         if (!language.IsEmpty()) {
           if (!nsContentUtils::IsJavaScriptLanguage(language)) {
             return false;
           }
         }
       }
     }
   }
 
   // "In modern user agents that support module scripts, the script element with
   // the nomodule attribute will be ignored".
   // "The nomodule attribute must not be specified on module scripts (and will
   // be ignored if it is)."
   if (ModuleScriptsEnabled() &&
       scriptKind == ScriptKind::Classic &&
       scriptContent->IsHTMLElement() &&
-      scriptContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::nomodule)) {
+      scriptContent->HasAttr(kNameSpaceID_None, nsGkAtoms::nomodule)) {
     return false;
   }
 
   // Step 15. and later in the HTML5 spec
   nsresult rv = NS_OK;
   RefPtr<ScriptLoadRequest> request;
   mozilla::net::ReferrerPolicy ourRefPolicy = mDocument->GetReferrerPolicy();
   if (aElement->GetScriptExternal()) {
@@ -1405,19 +1399,18 @@ ScriptLoader::ProcessScriptElement(nsISc
     }
 
     if (!request) {
       // no usable preload
 
       SRIMetadata sriMetadata;
       {
         nsAutoString integrity;
-        scriptContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                            nsGkAtoms::integrity,
-                                            integrity);
+        scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::integrity,
+                               integrity);
         if (!integrity.IsEmpty()) {
           MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
                   ("ScriptLoader::ProcessScriptElement, integrity=%s",
                    NS_ConvertUTF16toUTF8(integrity).get()));
           nsAutoCString sourceUri;
           if (mDocument->GetDocumentURI()) {
             mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
           }
--- a/dom/svg/SVGAElement.cpp
+++ b/dom/svg/SVGAElement.cpp
@@ -261,38 +261,38 @@ SVGAElement::IsLink(nsIURI** aURI) const
   //   xlink:href    - must be set
   //   xlink:type    - must be unset or set to "" or set to "simple"
   //   xlink:show    - must be unset or set to "", "new" or "replace"
   //   xlink:actuate - must be unset or set to "" or "onRequest"
   //
   // For any other values, we're either not a *clickable* XLink, or the end
   // result is poorly specified. Either way, we return false.
 
-  static Element::AttrValuesArray sTypeVals[] =
+  static nsIContent::AttrValuesArray sTypeVals[] =
     { &nsGkAtoms::_empty, &nsGkAtoms::simple, nullptr };
 
-  static Element::AttrValuesArray sShowVals[] =
+  static nsIContent::AttrValuesArray sShowVals[] =
     { &nsGkAtoms::_empty, &nsGkAtoms::_new, &nsGkAtoms::replace, nullptr };
 
-  static Element::AttrValuesArray sActuateVals[] =
+  static nsIContent::AttrValuesArray sActuateVals[] =
     { &nsGkAtoms::_empty, &nsGkAtoms::onRequest, nullptr };
 
   // Optimization: check for href first for early return
   bool useBareHref = mStringAttributes[HREF].IsExplicitlySet();
 
   if ((useBareHref || mStringAttributes[XLINK_HREF].IsExplicitlySet()) &&
       FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::type,
                       sTypeVals, eCaseMatters) !=
-                      Element::ATTR_VALUE_NO_MATCH &&
+                      nsIContent::ATTR_VALUE_NO_MATCH &&
       FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
                       sShowVals, eCaseMatters) !=
-                      Element::ATTR_VALUE_NO_MATCH &&
+                      nsIContent::ATTR_VALUE_NO_MATCH &&
       FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::actuate,
                       sActuateVals, eCaseMatters) !=
-                      Element::ATTR_VALUE_NO_MATCH) {
+                      nsIContent::ATTR_VALUE_NO_MATCH) {
     nsCOMPtr<nsIURI> baseURI = GetBaseURI();
     // Get absolute URI
     nsAutoString str;
     const uint8_t idx = useBareHref ? HREF : XLINK_HREF;
     mStringAttributes[idx].GetAnimValue(str, this);
     nsContentUtils::NewURIWithDocumentCharset(aURI, str, OwnerDoc(), baseURI);
     // must promise out param is non-null if we return true
     return !!*aURI;
@@ -303,17 +303,17 @@ SVGAElement::IsLink(nsIURI** aURI) const
 }
 
 void
 SVGAElement::GetLinkTarget(nsAString& aTarget)
 {
   mStringAttributes[TARGET].GetAnimValue(aTarget, this);
   if (aTarget.IsEmpty()) {
 
-    static Element::AttrValuesArray sShowVals[] =
+    static nsIContent::AttrValuesArray sShowVals[] =
       { &nsGkAtoms::_new, &nsGkAtoms::replace, nullptr };
 
     switch (FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
                             sShowVals, eCaseMatters)) {
     case 0:
       aTarget.AssignLiteral("_blank");
       return;
     case 1:
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -1541,17 +1541,17 @@ nsXBLPrototypeBinding::WriteNamespace(ns
   }
 
   return NS_OK;
 }
 
 
 bool CheckTagNameWhiteList(int32_t aNameSpaceID, nsAtom *aTagName)
 {
-  static Element::AttrValuesArray kValidXULTagNames[] =  {
+  static nsIContent::AttrValuesArray kValidXULTagNames[] =  {
     &nsGkAtoms::autorepeatbutton, &nsGkAtoms::box, &nsGkAtoms::browser,
     &nsGkAtoms::button, &nsGkAtoms::hbox, &nsGkAtoms::image, &nsGkAtoms::menu,
     &nsGkAtoms::menubar, &nsGkAtoms::menuitem, &nsGkAtoms::menupopup,
     &nsGkAtoms::row, &nsGkAtoms::slider, &nsGkAtoms::spacer,
     &nsGkAtoms::splitter, &nsGkAtoms::text, &nsGkAtoms::tree, nullptr};
 
   uint32_t i;
   if (aNameSpaceID == kNameSpaceID_XUL) {
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -99,17 +99,17 @@ nsXBLPrototypeHandler::nsXBLPrototypeHan
 {
   Init();
 
   ConstructPrototype(nullptr, aEvent, aPhase, aAction, aCommand, aKeyCode,
                      aCharCode, aModifiers, aButton, aClickCount,
                      aGroup, aPreventDefault, aAllowUntrusted);
 }
 
-nsXBLPrototypeHandler::nsXBLPrototypeHandler(Element* aHandlerElement, XBLReservedKey aReserved)
+nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement, XBLReservedKey aReserved)
   : mHandlerElement(nullptr),
     mLineNumber(0),
     mReserved(aReserved),
     mNextHandler(nullptr),
     mPrototypeBinding(nullptr)
 {
   Init();
 
@@ -195,21 +195,21 @@ nsXBLPrototypeHandler::TryConvertToKeybo
                            keyCode,
                            charCode,
                            modifiers,
                            modifiersMask,
                            action);
   return true;
 }
 
-already_AddRefed<Element>
+already_AddRefed<nsIContent>
 nsXBLPrototypeHandler::GetHandlerElement()
 {
   if (mType & NS_HANDLER_TYPE_XUL) {
-    nsCOMPtr<Element> element = do_QueryReferent(mHandlerElement);
+    nsCOMPtr<nsIContent> element = do_QueryReferent(mHandlerElement);
     return element.forget();
   }
 
   return nullptr;
 }
 
 void
 nsXBLPrototypeHandler::AppendHandlerText(const nsAString& aText)
@@ -568,17 +568,17 @@ nsXBLPrototypeHandler::DispatchXBLComman
     controller->DoCommand(command.get());
 
   return NS_OK;
 }
 
 nsresult
 nsXBLPrototypeHandler::DispatchXULKeyCommand(nsIDOMEvent* aEvent)
 {
-  nsCOMPtr<Element> handlerElement = GetHandlerElement();
+  nsCOMPtr<nsIContent> handlerElement = GetHandlerElement();
   NS_ENSURE_STATE(handlerElement);
   if (handlerElement->AttrValueIs(kNameSpaceID_None,
                                   nsGkAtoms::disabled,
                                   nsGkAtoms::_true,
                                   eCaseMatters)) {
     // Don't dispatch command events for disabled keys.
     return NS_OK;
   }
@@ -831,30 +831,30 @@ nsXBLPrototypeHandler::AccelKeyMask()
       MOZ_CRASH("Handle the new result of WidgetInputEvent::AccelModifier()");
       return 0;
   }
 }
 
 void
 nsXBLPrototypeHandler::GetEventType(nsAString& aEvent)
 {
-  nsCOMPtr<Element> handlerElement = GetHandlerElement();
+  nsCOMPtr<nsIContent> handlerElement = GetHandlerElement();
   if (!handlerElement) {
     aEvent.Truncate();
     return;
   }
   handlerElement->GetAttr(kNameSpaceID_None, nsGkAtoms::event, aEvent);
 
   if (aEvent.IsEmpty() && (mType & NS_HANDLER_TYPE_XUL))
     // If no type is specified for a XUL <key> element, let's assume that we're "keypress".
     aEvent.AssignLiteral("keypress");
 }
 
 void
-nsXBLPrototypeHandler::ConstructPrototype(Element* aKeyElement,
+nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement,
                                           const char16_t* aEvent,
                                           const char16_t* aPhase,
                                           const char16_t* aAction,
                                           const char16_t* aCommand,
                                           const char16_t* aKeyCode,
                                           const char16_t* aCharCode,
                                           const char16_t* aModifiers,
                                           const char16_t* aButton,
@@ -1005,17 +1005,17 @@ nsXBLPrototypeHandler::ConstructPrototyp
       mType |= NS_HANDLER_ALLOW_UNTRUSTED;
     } else {
       mType &= ~NS_HANDLER_ALLOW_UNTRUSTED;
     }
   }
 }
 
 void
-nsXBLPrototypeHandler::ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, Element* aKeyElement, const char *aMessageName)
+nsXBLPrototypeHandler::ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, nsIContent* aKeyElement, const char *aMessageName)
 {
   nsCOMPtr<nsIDocument> doc;
   if (mPrototypeBinding) {
     nsXBLDocumentInfo* docInfo = mPrototypeBinding->XBLDocumentInfo();
     if (docInfo) {
       doc = docInfo->GetDocument();
     }
   } else {
--- a/dom/xbl/nsXBLPrototypeHandler.h
+++ b/dom/xbl/nsXBLPrototypeHandler.h
@@ -59,22 +59,16 @@ class KeyboardShortcut;
 // the permissions.default.shortcuts preference.
 enum XBLReservedKey : uint8_t
 {
   XBLReservedKey_False = 0,
   XBLReservedKey_True = 1,
   XBLReservedKey_Unset = 2,
 };
 
-namespace mozilla {
-namespace dom {
-class Element;
-}
-}
-
 class nsXBLPrototypeHandler
 {
   typedef mozilla::IgnoreModifierState IgnoreModifierState;
   typedef mozilla::layers::KeyboardShortcut KeyboardShortcut;
   typedef mozilla::Modifiers Modifiers;
 
 public:
   // This constructor is used by XBL handlers (both the JS and command shorthand variety)
@@ -84,17 +78,17 @@ public:
                         const char16_t* aModifiers, const char16_t* aButton,
                         const char16_t* aClickCount, const char16_t* aGroup,
                         const char16_t* aPreventDefault,
                         const char16_t* aAllowUntrusted,
                         nsXBLPrototypeBinding* aBinding,
                         uint32_t aLineNumber);
 
   // This constructor is used only by XUL key handlers (e.g., <key>)
-  explicit nsXBLPrototypeHandler(mozilla::dom::Element* aKeyElement, XBLReservedKey aReserved);
+  explicit nsXBLPrototypeHandler(nsIContent* aKeyElement, XBLReservedKey aReserved);
 
   // This constructor is used for handlers loaded from the cache
   explicit nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding);
 
   ~nsXBLPrototypeHandler();
 
   /**
    * Try and convert this XBL handler into an APZ KeyboardShortcut for handling
@@ -122,17 +116,17 @@ public:
                                   nsIDOMMouseEvent* aEvent)
   {
     if (!EventTypeEquals(aEventType)) {
       return false;
     }
     return MouseEventMatched(aEvent);
   }
 
-  already_AddRefed<mozilla::dom::Element> GetHandlerElement();
+  already_AddRefed<nsIContent> GetHandlerElement();
 
   void AppendHandlerText(const nsAString& aText);
 
   uint8_t GetPhase() { return mPhase; }
   uint8_t GetType() { return mType; }
   XBLReservedKey GetIsReserved() { return mReserved; }
 
   nsXBLPrototypeHandler* GetNextHandler() { return mNextHandler; }
@@ -181,26 +175,26 @@ protected:
     if (gRefCnt == 1)
       // Get the primary accelerator key.
       InitAccessKeys();
   }
 
   already_AddRefed<nsIController> GetController(mozilla::dom::EventTarget* aTarget);
 
   inline int32_t GetMatchingKeyCode(const nsAString& aKeyName);
-  void ConstructPrototype(mozilla::dom::Element* aKeyElement,
+  void ConstructPrototype(nsIContent* aKeyElement,
                           const char16_t* aEvent=nullptr, const char16_t* aPhase=nullptr,
                           const char16_t* aAction=nullptr, const char16_t* aCommand=nullptr,
                           const char16_t* aKeyCode=nullptr, const char16_t* aCharCode=nullptr,
                           const char16_t* aModifiers=nullptr, const char16_t* aButton=nullptr,
                           const char16_t* aClickCount=nullptr, const char16_t* aGroup=nullptr,
                           const char16_t* aPreventDefault=nullptr,
                           const char16_t* aAllowUntrusted=nullptr);
 
-  void ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, mozilla::dom::Element* aElement, const char *aMessageName);
+  void ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, nsIContent* aElement, const char *aMessageName);
   void GetEventType(nsAString& type);
   bool ModifiersMatchMask(nsIDOMUIEvent* aEvent,
                           const IgnoreModifierState& aIgnoreModifierState);
   nsresult DispatchXBLCommand(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent);
   nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent);
   nsresult EnsureEventHandler(mozilla::dom::AutoJSAPI& jsapi, nsAtom* aName,
                               JS::MutableHandle<JSObject*> aHandler);
 
--- a/dom/xbl/nsXBLWindowKeyHandler.cpp
+++ b/dom/xbl/nsXBLWindowKeyHandler.cpp
@@ -192,49 +192,45 @@ BuildHandlerChain(nsIContent* aContent, 
   *aResult = nullptr;
 
   // Since we chain each handler onto the next handler,
   // we'll enumerate them here in reverse so that when we
   // walk the chain they'll come out in the original order
   for (nsIContent* key = aContent->GetLastChild();
        key;
        key = key->GetPreviousSibling()) {
-    if (!key->NodeInfo()->Equals(nsGkAtoms::key, kNameSpaceID_XUL)) {
-      continue;
-    }
 
-    Element* keyElement = key->AsElement();
-    // Check whether the key element has empty value at key/char attribute.
-    // Such element is used by localizers for alternative shortcut key
-    // definition on the locale. See bug 426501.
-    nsAutoString valKey, valCharCode, valKeyCode;
-    bool attrExists =
-      keyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::key, valKey) ||
-      keyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, valCharCode) ||
-      keyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, valKeyCode);
-    if (attrExists &&
-        valKey.IsEmpty() && valCharCode.IsEmpty() && valKeyCode.IsEmpty())
-      continue;
+    if (key->NodeInfo()->Equals(nsGkAtoms::key, kNameSpaceID_XUL)) {
+      // Check whether the key element has empty value at key/char attribute.
+      // Such element is used by localizers for alternative shortcut key
+      // definition on the locale. See bug 426501.
+      nsAutoString valKey, valCharCode, valKeyCode;
+      bool attrExists =
+        key->GetAttr(kNameSpaceID_None, nsGkAtoms::key, valKey) ||
+        key->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, valCharCode) ||
+        key->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, valKeyCode);
+      if (attrExists &&
+          valKey.IsEmpty() && valCharCode.IsEmpty() && valKeyCode.IsEmpty())
+        continue;
 
-    // reserved="pref" is the default for <key> elements.
-    XBLReservedKey reserved = XBLReservedKey_Unset;
-    if (keyElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::reserved,
-                                nsGkAtoms::_true, eCaseMatters)) {
-      reserved = XBLReservedKey_True;
-    } else if (keyElement->AttrValueIs(kNameSpaceID_None,
-                                       nsGkAtoms::reserved,
-                                       nsGkAtoms::_false, eCaseMatters)) {
-      reserved = XBLReservedKey_False;
+      // reserved="pref" is the default for <key> elements.
+      XBLReservedKey reserved = XBLReservedKey_Unset;
+      if (key->AttrValueIs(kNameSpaceID_None, nsGkAtoms::reserved,
+                           nsGkAtoms::_true, eCaseMatters)) {
+        reserved = XBLReservedKey_True;
+      } else if (key->AttrValueIs(kNameSpaceID_None, nsGkAtoms::reserved,
+                                   nsGkAtoms::_false, eCaseMatters)) {
+        reserved = XBLReservedKey_False;
+      }
+
+      nsXBLPrototypeHandler* handler = new nsXBLPrototypeHandler(key, reserved);
+
+      handler->SetNextHandler(*aResult);
+      *aResult = handler;
     }
-
-    nsXBLPrototypeHandler* handler =
-      new nsXBLPrototypeHandler(keyElement, reserved);
-
-    handler->SetNextHandler(*aResult);
-    *aResult = handler;
   }
 }
 
 //
 // EnsureHandlers
 //
 // Lazily load the XBL handlers. Overridden to handle being attached
 // to a particular element rather than the document
@@ -869,17 +865,17 @@ nsXBLWindowKeyHandler::GetElement(bool* 
 
 bool
 nsXBLWindowKeyHandler::GetElementForHandler(nsXBLPrototypeHandler* aHandler,
                                             Element** aElementForHandler)
 {
   MOZ_ASSERT(aElementForHandler);
   *aElementForHandler = nullptr;
 
-  RefPtr<Element> keyContent = aHandler->GetHandlerElement();
+  nsCOMPtr<nsIContent> keyContent = aHandler->GetHandlerElement();
   if (!keyContent) {
     return true; // XXX Even though no key element?
   }
 
   nsCOMPtr<Element> chromeHandlerElement = GetElement();
   if (!chromeHandlerElement) {
     NS_WARNING_ASSERTION(keyContent->IsInUncomposedDoc(), "uncomposed");
     nsCOMPtr<Element> keyElement = do_QueryInterface(keyContent);
--- a/dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
+++ b/dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
@@ -279,22 +279,21 @@ txXPathNode::~txXPathNode()
     }
 }
 
 /* static */
 bool
 txXPathNodeUtils::getAttr(const txXPathNode& aNode, nsAtom* aLocalName,
                           int32_t aNSID, nsAString& aValue)
 {
-    if (aNode.isDocument() || aNode.isAttribute() ||
-        !aNode.Content()->IsElement()) {
+    if (aNode.isDocument() || aNode.isAttribute()) {
         return false;
     }
 
-    return aNode.Content()->AsElement()->GetAttr(aNSID, aLocalName, aValue);
+    return aNode.Content()->GetAttr(aNSID, aLocalName, aValue);
 }
 
 /* static */
 already_AddRefed<nsAtom>
 txXPathNodeUtils::getLocalName(const txXPathNode& aNode)
 {
     if (aNode.isDocument()) {
         return nullptr;
@@ -448,24 +447,23 @@ txXPathNodeUtils::getNodeType(const txXP
 /* static */
 void
 txXPathNodeUtils::appendNodeValue(const txXPathNode& aNode, nsAString& aResult)
 {
     if (aNode.isAttribute()) {
         const nsAttrName* name = aNode.Content()->AsElement()->GetAttrNameAt(aNode.mIndex);
 
         if (aResult.IsEmpty()) {
-            aNode.Content()->AsElement()->GetAttr(name->NamespaceID(),
-                                                  name->LocalName(),
-                                                  aResult);
-        } else {
+            aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
+                                     aResult);
+        }
+        else {
             nsAutoString result;
-            aNode.Content()->AsElement()->GetAttr(name->NamespaceID(),
-                                                  name->LocalName(),
-                                                  result);
+            aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
+                                     result);
             aResult.Append(result);
         }
 
         return;
     }
 
     if (aNode.isDocument() ||
         aNode.mNode->IsElement() ||
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -747,20 +747,20 @@ txMozillaXMLOutput::endHTMLElement(nsICo
         mTableState = static_cast<TableState>
                                  (NS_PTR_TO_INT32(mTableStateStack.pop()));
 
         return NS_OK;
     }
     else if (mCreatingNewDocument && aElement->IsHTMLElement(nsGkAtoms::meta)) {
         // handle HTTP-EQUIV data
         nsAutoString httpEquiv;
-        aElement->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, httpEquiv);
+        aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, httpEquiv);
         if (!httpEquiv.IsEmpty()) {
             nsAutoString value;
-            aElement->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::content, value);
+            aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::content, value);
             if (!value.IsEmpty()) {
                 nsContentUtils::ASCIIToLower(httpEquiv);
                 RefPtr<nsAtom> header = NS_Atomize(httpEquiv);
                 processHTTPEquiv(header, value);
             }
         }
     }
 
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -865,34 +865,34 @@ XULDocument::ExecuteOnBroadcastHandlerFo
     for (nsIContent* child = aListener->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
 
         // Look for an <observes> element beneath the listener. This
         // ought to have an |element| attribute that refers to
         // aBroadcaster, and an |attribute| element that tells us what
         // attriubtes we're listening for.
-        if (!child->IsXULElement(nsGkAtoms::observes))
+        if (!child->NodeInfo()->Equals(nsGkAtoms::observes, kNameSpaceID_XUL))
             continue;
 
         // Is this the element that was listening to us?
         nsAutoString listeningToID;
-        child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::element, listeningToID);
+        child->GetAttr(kNameSpaceID_None, nsGkAtoms::element, listeningToID);
 
         nsAutoString broadcasterID;
         aBroadcaster->GetAttr(kNameSpaceID_None, nsGkAtoms::id, broadcasterID);
 
         if (listeningToID != broadcasterID)
             continue;
 
         // We are observing the broadcaster, but is this the right
         // attribute?
         nsAutoString listeningToAttribute;
-        child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::attribute,
-                                    listeningToAttribute);
+        child->GetAttr(kNameSpaceID_None, nsGkAtoms::attribute,
+                       listeningToAttribute);
 
         if (!aAttr->Equals(listeningToAttribute) &&
             !listeningToAttribute.EqualsLiteral("*")) {
             continue;
         }
 
         // This is the right <observes> element. Execute the
         // |onbroadcast| event handler
@@ -1031,17 +1031,17 @@ XULDocument::AttributeChanged(nsIDocumen
     // XXX Namespace handling broken :-(
     nsAutoString persist;
     aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::persist, persist);
     // Persistence of attributes of xul:window is handled in nsXULWindow.
     if (ShouldPersistAttribute(aElement, aAttribute) && !persist.IsEmpty() &&
         // XXXldb This should check that it's a token, not just a substring.
         persist.Find(nsDependentAtomString(aAttribute)) >= 0) {
       nsContentUtils::AddScriptRunner(
-        NewRunnableMethod<Element*, int32_t, nsAtom*>(
+        NewRunnableMethod<nsIContent*, int32_t, nsAtom*>(
           "dom::XULDocument::DoPersist",
           this,
           &XULDocument::DoPersist,
           aElement,
           kNameSpaceID_None,
           aAttribute));
     }
 }
@@ -1303,17 +1303,17 @@ XULDocument::Persist(const nsAString& aI
 
         nameSpaceID = kNameSpaceID_None;
     }
 
     return Persist(element, nameSpaceID, tag);
 }
 
 nsresult
-XULDocument::Persist(Element* aElement, int32_t aNameSpaceID,
+XULDocument::Persist(nsIContent* aElement, int32_t aNameSpaceID,
                      nsAtom* aAttribute)
 {
     // For non-chrome documents, persistance is simply broken
     if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()))
         return NS_ERROR_NOT_AVAILABLE;
 
     if (!mLocalStore) {
         mLocalStore = do_GetService("@mozilla.org/xul/xulstore;1");
@@ -3626,17 +3626,17 @@ XULDocument::AddAttributes(nsXULPrototyp
         if (NS_FAILED(rv)) return rv;
     }
 
     return NS_OK;
 }
 
 
 nsresult
-XULDocument::CheckTemplateBuilderHookup(Element* aElement,
+XULDocument::CheckTemplateBuilderHookup(nsIContent* aElement,
                                         bool* aNeedsHookup)
 {
     // See if the element already has a `database' attribute. If it
     // does, then the template builder has already been created.
     //
     // XXX This approach will crash and burn (well, maybe not _that_
     // bad) if aElement is not a XUL element.
     //
@@ -4255,25 +4255,21 @@ XULDocument::InsertElement(nsINode* aPar
 {
     // Insert aChild appropriately into aParent, accounting for a
     // 'pos' attribute set on aChild.
 
     nsAutoString posStr;
     bool wasInserted = false;
 
     // insert after an element of a given id
-    if (aChild->IsElement()) {
-        aChild->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::insertafter, posStr);
-    }
-
+    aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::insertafter, posStr);
     bool isInsertAfter = true;
+
     if (posStr.IsEmpty()) {
-        if (aChild->IsElement()) {
-            aChild->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::insertbefore, posStr);
-        }
+        aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::insertbefore, posStr);
         isInsertAfter = false;
     }
 
     if (!posStr.IsEmpty()) {
         nsIDocument *document = aParent->OwnerDoc();
 
         nsIContent *content = nullptr;
 
@@ -4300,19 +4296,18 @@ XULDocument::InsertElement(nsINode* aPar
                     return rv;
 
                 wasInserted = true;
             }
         }
     }
 
     if (!wasInserted) {
-        if (aChild->IsElement() &&
-            aChild->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::position, posStr) &&
-            !posStr.IsEmpty()) {
+        aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::position, posStr);
+        if (!posStr.IsEmpty()) {
             nsresult rv;
             // Positions are one-indexed.
             int32_t pos = posStr.ToInteger(&rv);
             // Note: if the insertion index (which is |pos - 1|) would be less
             // than 0 or greater than the number of children aParent has, then
             // don't insert, since the position is bogus.  Just skip on to
             // appending.
             if (NS_SUCCEEDED(rv) && pos > 0 &&
@@ -4478,17 +4473,17 @@ XULDocument::GetWindowRoot()
 
 bool
 XULDocument::IsDocumentRightToLeft()
 {
     // setting the localedir attribute on the root element forces a
     // specific direction for the document.
     Element* element = GetRootElement();
     if (element) {
-        static Element::AttrValuesArray strings[] =
+        static nsIContent::AttrValuesArray strings[] =
             {&nsGkAtoms::ltr, &nsGkAtoms::rtl, nullptr};
         switch (element->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::localedir,
                                          strings, eCaseMatters)) {
             case 0: return false;
             case 1: return true;
             default: break; // otherwise, not a valid value, so fall through
         }
     }
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -293,24 +293,20 @@ protected:
     static nsIRDFService* gRDFService;
     static nsIRDFResource* kNC_persist;
     static nsIRDFResource* kNC_attribute;
     static nsIRDFResource* kNC_value;
 
     static LazyLogModule gXULLog;
 
     nsresult
-    Persist(mozilla::dom::Element* aElement,
-            int32_t aNameSpaceID,
-            nsAtom* aAttribute);
+    Persist(nsIContent* aElement, int32_t aNameSpaceID, nsAtom* aAttribute);
     // Just like Persist but ignores the return value so we can use it
     // as a runnable method.
-    void DoPersist(mozilla::dom::Element* aElement,
-                   int32_t aNameSpaceID,
-                   nsAtom* aAttribute)
+    void DoPersist(nsIContent* aElement, int32_t aNameSpaceID, nsAtom* aAttribute)
     {
         Persist(aElement, aNameSpaceID, aAttribute);
     }
 
     virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
     // IMPORTANT: The ownership implicit in the following member
     // variables has been explicitly checked and set using nsCOMPtr
@@ -467,17 +463,17 @@ protected:
      */
     char16_t* mOffThreadCompileStringBuf;
     size_t mOffThreadCompileStringLength;
 
     /**
      * Check if a XUL template builder has already been hooked up.
      */
     static nsresult
-    CheckTemplateBuilderHookup(mozilla::dom::Element* aElement, bool* aNeedsHookup);
+    CheckTemplateBuilderHookup(nsIContent* aElement, bool* aNeedsHookup);
 
     /**
      * Create a XUL template builder on the specified node.
      */
     static nsresult
     CreateTemplateBuilder(Element* aElement);
 
     /**
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -967,30 +967,29 @@ nsXULElement::UnregisterAccessKey(const 
 {
     // If someone changes the accesskey, unregister the old one
     //
     nsIDocument* doc = GetComposedDoc();
     if (doc && !aOldValue.IsEmpty()) {
         nsIPresShell *shell = doc->GetShell();
 
         if (shell) {
-            Element* element = this;
+            nsIContent *content = this;
 
             // find out what type of content node this is
             if (mNodeInfo->Equals(nsGkAtoms::label)) {
                 // For anonymous labels the unregistering must
                 // occur on the binding parent control.
                 // XXXldb: And what if the binding parent is null?
-                nsIContent* bindingParent = GetBindingParent();
-                element = bindingParent ? bindingParent->AsElement() : nullptr;
+                content = GetBindingParent();
             }
 
-            if (element) {
+            if (content) {
                 shell->GetPresContext()->EventStateManager()->
-                    UnregisterAccessKey(element, aOldValue.First());
+                    UnregisterAccessKey(content, aOldValue.First());
             }
         }
     }
 }
 
 nsresult
 nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
                             const nsAttrValueOrString* aValue, bool aNotify)
--- a/dom/xul/nsXULPopupListener.cpp
+++ b/dom/xul/nsXULPopupListener.cpp
@@ -304,24 +304,24 @@ nsXULPopupListener::ClosePopup()
     // fire events during destruction.
     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     if (pm)
       pm->HidePopup(mPopupContent, false, true, true, false);
     mPopupContent = nullptr;  // release the popup
   }
 } // ClosePopup
 
-static already_AddRefed<Element>
+static already_AddRefed<nsIContent>
 GetImmediateChild(nsIContent* aContent, nsAtom *aTag)
 {
   for (nsIContent* child = aContent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->IsXULElement(aTag)) {
-      RefPtr<Element> ret = child->AsElement();
+      nsCOMPtr<nsIContent> ret = child;
       return ret.forget();
     }
   }
 
   return nullptr;
 }
 
 //
@@ -365,17 +365,17 @@ nsXULPopupListener::LaunchPopup(nsIDOMEv
   // Try to find the popup content and the document.
   nsCOMPtr<nsIDocument> document = mElement->GetComposedDoc();
   if (!document) {
     NS_WARNING("No document!");
     return NS_ERROR_FAILURE;
   }
 
   // Handle the _child case for popups and context menus
-  RefPtr<Element> popup;
+  nsCOMPtr<nsIContent> popup;
   if (identifier.EqualsLiteral("_child")) {
     popup = GetImmediateChild(mElement, nsGkAtoms::menupopup);
     if (!popup) {
       nsCOMPtr<nsIDOMDocumentXBL> nsDoc(do_QueryInterface(document));
       nsCOMPtr<nsIDOMNodeList> list;
       nsCOMPtr<nsIDOMElement> el = do_QueryInterface(mElement);
       nsDoc->GetAnonymousNodes(el, getter_AddRefs(list));
       if (list) {
@@ -383,17 +383,17 @@ nsXULPopupListener::LaunchPopup(nsIDOMEv
         nsCOMPtr<nsIDOMNode> node;
         list->GetLength(&listLength);
         for (ctr = 0; ctr < listLength; ctr++) {
           list->Item(ctr, getter_AddRefs(node));
           nsCOMPtr<nsIContent> childContent(do_QueryInterface(node));
 
           if (childContent->NodeInfo()->Equals(nsGkAtoms::menupopup,
                                                kNameSpaceID_XUL)) {
-            popup = childContent->AsElement();
+            popup.swap(childContent);
             break;
           }
         }
       }
     }
   } else if (!mElement->IsInUncomposedDoc() ||
              !(popup = document->GetElementById(identifier))) {
     // XXXsmaug Should we try to use ShadowRoot::GetElementById in case
--- a/dom/xul/nsXULPopupListener.h
+++ b/dom/xul/nsXULPopupListener.h
@@ -44,18 +44,18 @@ protected:
 
 private:
 #ifndef NS_CONTEXT_MENU_IS_MOUSEUP
     // When a context menu is opened, focus the target of the contextmenu event.
     nsresult FireFocusOnTargetContent(nsIDOMNode* aTargetNode, bool aIsTouch);
 #endif
 
     // |mElement| is the node to which this listener is attached.
-    RefPtr<mozilla::dom::Element> mElement;
+    nsCOMPtr<mozilla::dom::Element> mElement;
 
     // The popup that is getting shown on top of mElement.
-    RefPtr<mozilla::dom::Element> mPopupContent;
+    nsCOMPtr<nsIContent> mPopupContent;
 
     // true if a context popup
     bool mIsContext;
 };
 
 #endif // nsXULPopupListener_h___
--- a/dom/xul/templates/nsXULContentBuilder.cpp
+++ b/dom/xul/templates/nsXULContentBuilder.cpp
@@ -498,19 +498,17 @@ nsXULContentBuilder::BuildContentFromTem
         // isGenerationElement will be true for the generation element,
         // and both will be false for descendants
         bool isGenerationElement = false;
         bool isUnique = aIsUnique;
 
         // We identify the resource element by presence of a
         // "uri='rdf:*'" attribute. (We also support the older
         // "uri='...'" syntax.)
-        if (tmplKid->IsElement() &&
-            tmplKid->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::uri) &&
-            aMatch->IsActive()) {
+        if (tmplKid->HasAttr(kNameSpaceID_None, nsGkAtoms::uri) && aMatch->IsActive()) {
             isGenerationElement = true;
             isUnique = false;
         }
 
         MOZ_ASSERT_IF(isGenerationElement, tmplKid->IsElement());
 
         nsAtom* tag = tmplKid->NodeInfo()->NameAtom();
 
@@ -607,18 +605,17 @@ nsXULContentBuilder::BuildContentFromTem
         } else if (tag == nsGkAtoms::textnode &&
                    nameSpaceID == kNameSpaceID_XUL) {
             // <xul:text value="..."> is replaced by text of the
             // actual value of the 'rdf:resource' attribute for the
             // given node.
             // SynchronizeUsingTemplate contains code used to update textnodes,
             // so make sure to modify both when changing this
             nsAutoString attrValue;
-            tmplKid->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value,
-                                          attrValue);
+            tmplKid->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue);
             if (!attrValue.IsEmpty()) {
                 nsAutoString value;
                 rv = SubstituteText(aChild, attrValue, value);
                 if (NS_FAILED(rv)) return rv;
 
                 RefPtr<nsTextNode> content =
                   new nsTextNode(mRoot->NodeInfo()->NodeInfoManager());
 
@@ -883,18 +880,17 @@ nsXULContentBuilder::SynchronizeUsingTem
         if (! realKid)
             break;
 
         // check for text nodes and update them accordingly.
         // This code is similar to that in BuildContentFromTemplate
         if (tmplKid->NodeInfo()->Equals(nsGkAtoms::textnode,
                                         kNameSpaceID_XUL)) {
             nsAutoString attrValue;
-            tmplKid->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value,
-                                          attrValue);
+            tmplKid->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue);
             if (!attrValue.IsEmpty()) {
                 nsAutoString value;
                 rv = SubstituteText(aResult, attrValue, value);
                 if (NS_FAILED(rv)) return rv;
                 realKid->SetText(value, true);
             }
         }
 
@@ -1256,18 +1252,18 @@ nsXULContentBuilder::IsOpen(nsIContent* 
     // Determine if this is a <treeitem> or <menu> element
 
     // XXXhyatt Use the XBL service to obtain a base tag.
     if (aElement->IsAnyOfXULElements(nsGkAtoms::menu,
                                      nsGkAtoms::menubutton,
                                      nsGkAtoms::toolbarbutton,
                                      nsGkAtoms::button,
                                      nsGkAtoms::treeitem))
-        return aElement->AsElement()->AttrValueIs(
-            kNameSpaceID_None, nsGkAtoms::open, nsGkAtoms::_true, eCaseMatters);
+        return aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::open,
+                                     nsGkAtoms::_true, eCaseMatters);
     return true;
 }
 
 nsresult
 nsXULContentBuilder::RemoveGeneratedContent(nsIContent* aElement)
 {
     // Keep a queue of "ungenerated" elements that we have to probe
     // for generated content.
--- a/dom/xul/templates/nsXULContentUtils.cpp
+++ b/dom/xul/templates/nsXULContentUtils.cpp
@@ -256,17 +256,17 @@ nsXULContentUtils::GetResource(int32_t a
     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get resource");
     if (NS_FAILED(rv)) return rv;
 
     return NS_OK;
 }
 
 
 nsresult
-nsXULContentUtils::SetCommandUpdater(nsIDocument* aDocument, Element* aElement)
+nsXULContentUtils::SetCommandUpdater(nsIDocument* aDocument, nsIContent* aElement)
 {
     // Deal with setting up a 'commandupdater'. Pulls the 'events' and
     // 'targets' attributes off of aElement, and adds it to the
     // document's command dispatcher.
     NS_PRECONDITION(aDocument != nullptr, "null ptr");
     if (! aDocument)
         return NS_ERROR_NULL_POINTER;
 
--- a/dom/xul/templates/nsXULContentUtils.h
+++ b/dom/xul/templates/nsXULContentUtils.h
@@ -121,17 +121,17 @@ public:
 
     static nsresult
     GetResource(int32_t aNameSpaceID, nsAtom* aAttribute, nsIRDFResource** aResult);
 
     static nsresult
     GetResource(int32_t aNameSpaceID, const nsAString& aAttribute, nsIRDFResource** aResult);
 
     static nsresult
-    SetCommandUpdater(nsIDocument* aDocument, mozilla::dom::Element* aElement);
+    SetCommandUpdater(nsIDocument* aDocument, nsIContent* aElement);
 
     /**
      * Log a message to the error console
      */
     static void
     LogTemplateError(const char* aMsg);
 
     static nsIRDFService*
--- a/dom/xul/templates/nsXULSortService.cpp
+++ b/dom/xul/templates/nsXULSortService.cpp
@@ -61,20 +61,20 @@ XULSortServiceImpl::SetSortColumnHints(n
   // column header sort indicator is updated properly.
   for (nsIContent* child = content->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->IsXULElement(nsGkAtoms::treecols)) {
       SetSortColumnHints(child, sortResource, sortDirection);
     } else if (child->IsXULElement(nsGkAtoms::treecol)) {
       nsAutoString value;
-      child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, value);
+      child->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, value);
       // also check the resource attribute for older code
       if (value.IsEmpty())
-        child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::resource, value);
+        child->GetAttr(kNameSpaceID_None, nsGkAtoms::resource, value);
       if (value == sortResource) {
         child->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::sortActive,
                                     NS_LITERAL_STRING("true"), true);
 
         child->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection,
                                     sortDirection, true);
         // Note: don't break out of loop; want to set/unset
         // attribs on ALL sort columns
@@ -189,28 +189,22 @@ testSortCallback(const void *data1, cons
     for (int32_t t = 0; t < length; t++) {
       // for templates, use the query processor to do sorting
       if (sortState->processor) {
         sortState->processor->CompareResults(left->result, right->result,
                                              sortState->sortKeys[t],
                                              sortState->sortHints, &sortOrder);
         if (sortOrder)
           break;
-      } else {
+      }
+      else {
         // no template, so just compare attributes. Ignore namespaces for now.
         nsAutoString leftstr, rightstr;
-        if (left->content->IsElement()) {
-          left->content->AsElement()->GetAttr(kNameSpaceID_None,
-                                              sortState->sortKeys[t],
-                                              leftstr);
-        }
-        if (right->content->IsElement()) {
-          right->content->AsElement()->GetAttr(kNameSpaceID_None,
-                                               sortState->sortKeys[t], rightstr);
-        }
+        left->content->GetAttr(kNameSpaceID_None, sortState->sortKeys[t], leftstr);
+        right->content->GetAttr(kNameSpaceID_None, sortState->sortKeys[t], rightstr);
 
         sortOrder = XULSortServiceImpl::CompareValues(leftstr, rightstr, sortState->sortHints);
       }
     }
   }
 
   if (sortState->direction == nsSortState_descending)
     sortOrder = -sortOrder;
@@ -287,20 +281,18 @@ XULSortServiceImpl::SortContainer(nsICon
   {
     nsIContent* child = items[i].content;
     nsIContent* parent = items[i].parent;
     if (parent) {
       parent->AppendChildTo(child, true);
 
       // if it's a container in a tree or menu, find its children,
       // and sort those also
-      if (!child->IsElement() ||
-          !child->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::container,
-                                           nsGkAtoms::_true, eCaseMatters))
+      if (!child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::container,
+                              nsGkAtoms::_true, eCaseMatters))
         continue;
 
       for (nsIContent* grandchild = child->GetFirstChild();
            grandchild;
            grandchild = grandchild->GetNextSibling()) {
         mozilla::dom::NodeInfo *ni = grandchild->NodeInfo();
         nsAtom *localName = ni->NameAtom();
         if (ni->NamespaceID() == kNameSpaceID_XUL &&
--- a/dom/xul/templates/nsXULTemplateBuilder.cpp
+++ b/dom/xul/templates/nsXULTemplateBuilder.cpp
@@ -2152,19 +2152,17 @@ already_AddRefed<nsAtom>
 nsXULTemplateBuilder::DetermineMemberVariable(nsIContent* aElement)
 {
     // recursively iterate over the children looking for an element
     // with uri="?..."
     for (nsIContent* child = aElement->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
         nsAutoString uri;
-        if (child->IsElement()) {
-          child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::uri, uri);
-        }
+        child->GetAttr(kNameSpaceID_None, nsGkAtoms::uri, uri);
         if (!uri.IsEmpty() && uri[0] == char16_t('?')) {
             return NS_Atomize(uri);
         }
 
         RefPtr<nsAtom> result = DetermineMemberVariable(child);
         if (result) {
             return result.forget();
         }
@@ -2251,46 +2249,45 @@ nsXULTemplateBuilder::CompileSimpleQuery
 
     *aCanUseTemplate = true;
 
     return AddSimpleRuleBindings(rule, aRuleElement);
 }
 
 nsresult
 nsXULTemplateBuilder::CompileConditions(nsTemplateRule* aRule,
-                                        Element* aCondition)
+                                        nsIContent* aCondition)
 {
     nsAutoString tag;
     aCondition->GetAttr(kNameSpaceID_None, nsGkAtoms::parent, tag);
 
     if (!tag.IsEmpty()) {
         RefPtr<nsAtom> tagatom = NS_Atomize(tag);
         aRule->SetTag(tagatom);
     }
 
     nsTemplateCondition* currentCondition = nullptr;
 
     for (nsIContent* node = aCondition->GetFirstChild();
          node;
          node = node->GetNextSibling()) {
 
         if (node->NodeInfo()->Equals(nsGkAtoms::where, kNameSpaceID_XUL)) {
-            nsresult rv =
-              CompileWhereCondition(aRule, node->AsElement(), &currentCondition);
+            nsresult rv = CompileWhereCondition(aRule, node, &currentCondition);
             if (NS_FAILED(rv))
                 return rv;
         }
     }
 
     return NS_OK;
 }
 
 nsresult
 nsXULTemplateBuilder::CompileWhereCondition(nsTemplateRule* aRule,
-                                            Element* aCondition,
+                                            nsIContent* aCondition,
                                             nsTemplateCondition** aCurrentCondition)
 {
     // Compile a <where> condition, which must be of the form:
     //
     //   <where subject="?var1|string" rel="relation" value="?var2|string" />
     //
     //    The value of rel may be:
     //      equal - subject must be equal to object
@@ -2387,31 +2384,31 @@ nsXULTemplateBuilder::CompileBindings(ns
     nsresult rv;
 
     for (nsIContent* binding = aBindings->GetFirstChild();
          binding;
          binding = binding->GetNextSibling()) {
 
         if (binding->NodeInfo()->Equals(nsGkAtoms::binding,
                                         kNameSpaceID_XUL)) {
-            rv = CompileBinding(aRule, binding->AsElement());
+            rv = CompileBinding(aRule, binding);
             if (NS_FAILED(rv))
                 return rv;
         }
     }
 
     aRule->AddBindingsToQueryProcessor(mQueryProcessor);
 
     return NS_OK;
 }
 
 
 nsresult
 nsXULTemplateBuilder::CompileBinding(nsTemplateRule* aRule,
-                                     Element* aBinding)
+                                     nsIContent* aBinding)
 {
     // Compile a <binding> "condition", which must be of the form:
     //
     //   <binding subject="?var1"
     //            predicate="resource"
     //            object="?var2" />
     //
     // XXXwaterson Some day it would be cool to allow the 'predicate'
--- a/dom/xul/templates/nsXULTemplateBuilder.h
+++ b/dom/xul/templates/nsXULTemplateBuilder.h
@@ -266,44 +266,44 @@ public:
 
     /**
      * Compile the <conditions> tag in a rule
      *
      * @param aRule template rule
      * @param aConditions <conditions> element
      */
     nsresult
-    CompileConditions(nsTemplateRule* aRule, Element* aConditions);
+    CompileConditions(nsTemplateRule* aRule, nsIContent* aConditions);
 
     /**
      * Compile a <where> tag in a condition. The caller should set
      * *aCurrentCondition to null for the first condition. This value will be
      * updated to point to the new condition before returning. The conditions
      * will be added to the rule aRule by this method.
      *
      * @param aRule template rule
      * @param aCondition <where> element
      * @param aCurrentCondition compiled condition
      */
     nsresult
     CompileWhereCondition(nsTemplateRule* aRule,
-                          Element* aCondition,
+                          nsIContent* aCondition,
                           nsTemplateCondition** aCurrentCondition);
 
     /**
      * Compile the <bindings> for an extended template syntax rule.
      */
     nsresult
     CompileBindings(nsTemplateRule* aRule, nsIContent* aBindings);
 
     /**
      * Compile a single binding for an extended template syntax rule.
      */
     nsresult
-    CompileBinding(nsTemplateRule* aRule, Element* aBinding);
+    CompileBinding(nsTemplateRule* aRule, nsIContent* aBinding);
 
     /**
      * Add automatic bindings for simple rules
      */
     nsresult
     AddSimpleRuleBindings(nsTemplateRule* aRule, Element* aElement);
 
     static void
--- a/dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
@@ -155,17 +155,17 @@ NS_IMETHODIMP
 nsXULTemplateQueryProcessorRDF::GetDatasource(nsIArray* aDataSources,
                                               nsIDOMNode* aRootNode,
                                               bool aIsTrusted,
                                               nsIXULTemplateBuilder* aBuilder,
                                               bool* aShouldDelayBuilding,
                                               nsISupports** aResult)
 {
     nsCOMPtr<nsIRDFCompositeDataSource> compDB;
-    nsCOMPtr<Element> root = do_QueryInterface(aRootNode);
+    nsCOMPtr<nsIContent> root = do_QueryInterface(aRootNode);
     nsresult rv;
 
     *aResult = nullptr;
     *aShouldDelayBuilding = false;
 
     NS_ENSURE_TRUE(root, NS_ERROR_UNEXPECTED);
 
     // make sure the RDF service is set up
@@ -1105,19 +1105,17 @@ nsXULTemplateQueryProcessorRDF::ComputeC
     // should use to test for containment.
     nsresult rv;
 
     mContainmentProperties.Clear();
 
     nsCOMPtr<nsIContent> content = do_QueryInterface(aRootNode);
 
     nsAutoString containment;
-    if (content->IsElement()) {
-      content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::containment, containment);
-    }
+    content->GetAttr(kNameSpaceID_None, nsGkAtoms::containment, containment);
 
     uint32_t len = containment.Length();
     uint32_t offset = 0;
     while (offset < len) {
         while (offset < len && nsCRT::IsAsciiSpace(containment[offset]))
             ++offset;
 
         if (offset >= len)
@@ -1181,17 +1179,17 @@ nsXULTemplateQueryProcessorRDF::CompileE
             if (condition != aConditions->GetFirstChild()) {
                 nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_CONTENT_NOT_FIRST);
                 continue;
             }
 
             // check for <content tag='tag'/> which indicates that matches
             // should only be generated for items inside content with that tag
             nsAutoString tagstr;
-            condition->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tag, tagstr);
+            condition->GetAttr(kNameSpaceID_None, nsGkAtoms::tag, tagstr);
 
             RefPtr<nsAtom> tag;
             if (! tagstr.IsEmpty()) {
                 tag = NS_Atomize(tagstr);
             }
 
             nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(condition->GetComposedDoc());
             if (! doc)
@@ -1225,20 +1223,21 @@ nsresult
 nsXULTemplateQueryProcessorRDF::CompileQueryChild(nsAtom* aTag,
                                                   nsRDFQuery* aQuery,
                                                   nsIContent* aCondition,
                                                   TestNode* aParentNode,
                                                   TestNode** aResult)
 {
     nsresult rv = NS_OK;
 
-    if (aCondition->IsElement() && aTag == nsGkAtoms::triple) {
-        rv = CompileTripleCondition(aQuery, aCondition->AsElement(), aParentNode, aResult);
-    } else if (aCondition->IsElement() && aTag == nsGkAtoms::member) {
-        rv = CompileMemberCondition(aQuery, aCondition->AsElement(), aParentNode, aResult);
+    if (aTag == nsGkAtoms::triple) {
+        rv = CompileTripleCondition(aQuery, aCondition, aParentNode, aResult);
+    }
+    else if (aTag == nsGkAtoms::member) {
+        rv = CompileMemberCondition(aQuery, aCondition, aParentNode, aResult);
     }
     else if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Info)) {
         nsAutoString tagstr;
         aTag->ToString(tagstr);
 
         nsAutoCString tagstrC;
         LossyCopyUTF16toASCII(tagstr, tagstrC);
         MOZ_LOG(gXULTemplateLog, LogLevel::Info,
@@ -1275,17 +1274,17 @@ nsXULTemplateQueryProcessorRDF::ParseLit
             return rv;
         literal.forget(aResult);
     }
     return rv;
 }
 
 nsresult
 nsXULTemplateQueryProcessorRDF::CompileTripleCondition(nsRDFQuery* aQuery,
-                                                       Element* aCondition,
+                                                       nsIContent* aCondition,
                                                        TestNode* aParentNode,
                                                        TestNode** aResult)
 {
     // Compile a <triple> condition, which must be of the form:
     //
     //   <triple subject="?var1|resource"
     //           predicate="resource"
     //           object="?var2|resource|literal" />
@@ -1377,17 +1376,17 @@ nsXULTemplateQueryProcessorRDF::CompileT
         return rv;
 
     *aResult = testnode;
     return NS_OK;
 }
 
 nsresult
 nsXULTemplateQueryProcessorRDF::CompileMemberCondition(nsRDFQuery* aQuery,
-                                                       Element* aCondition,
+                                                       nsIContent* aCondition,
                                                        TestNode* aParentNode,
                                                        TestNode** aResult)
 {
     // Compile a <member> condition, which must be of the form:
     //
     //   <member container="?var1" child="?var2" />
     //
 
@@ -1522,17 +1521,17 @@ nsXULTemplateQueryProcessorRDF::CompileS
         TestNode* testnode = nullptr;
 
         if (name->Equals(nsGkAtoms::iscontainer, kNameSpaceID_None) ||
             name->Equals(nsGkAtoms::isempty, kNameSpaceID_None)) {
 
             nsRDFConInstanceTestNode::Test iscontainer =
                 nsRDFConInstanceTestNode::eDontCare;
 
-            static Element::AttrValuesArray strings[] =
+            static nsIContent::AttrValuesArray strings[] =
               {&nsGkAtoms::_true, &nsGkAtoms::_false, nullptr};
             switch (aQueryElement->FindAttrValueIn(kNameSpaceID_None,
                                                    nsGkAtoms::iscontainer,
                                                    strings, eCaseMatters)) {
                 case 0: iscontainer = nsRDFConInstanceTestNode::eTrue; break;
                 case 1: iscontainer = nsRDFConInstanceTestNode::eFalse; break;
             }
 
--- a/dom/xul/templates/nsXULTemplateQueryProcessorRDF.h
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorRDF.h
@@ -151,28 +151,28 @@ public:
 
     /**
      * Compile a <triple> condition and return the compiled node in aResult.
      * This node will have been added to mAllTests which owns the node and
      * set as a child of aParentNode.
      */
     nsresult
     CompileTripleCondition(nsRDFQuery* aQuery,
-                           Element* aCondition,
+                           nsIContent* aCondition,
                            TestNode* aParentNode,
                            TestNode** aResult);
 
     /**
      * Compile a <member> condition and return the compiled node in aResult.
      * This node will have been added to mAllTests which owns the node and
      * set as a child of aParentNode.
      */
     nsresult
     CompileMemberCondition(nsRDFQuery* aQuery,
-                           Element* aCondition,
+                           nsIContent* aCondition,
                            TestNode* aParentNode,
                            TestNode** aResult);
 
     /**
      * Add the default rules shared by all simple queries. This creates
      * the content start node followed by a member test. The member TestNode
      * is returned in aChildNode. Both nodes will have been added to mAllTests
      * which owns the nodes.
--- a/dom/xul/templates/nsXULTemplateQueryProcessorStorage.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorStorage.cpp
@@ -308,45 +308,41 @@ nsXULTemplateQueryProcessorStorage::Comp
             nsAutoString value;
             if (!nsContentUtils::GetNodeTextContent(child, false, value, fallible)) {
               return NS_ERROR_OUT_OF_MEMORY;
             }
 
             uint32_t index = parameterCount;
             nsAutoString name, indexValue;
 
-            if (child->AsElement()->GetAttr(kNameSpaceID_None,
-                                            nsGkAtoms::name,
-                                            name)) {
+            if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
                 rv = statement->GetParameterIndex(NS_ConvertUTF16toUTF8(name),
                                                   &index);
                 if (NS_FAILED(rv)) {
                     nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_UNKNOWN_QUERY_PARAMETER);
                     return rv;
                 }
                 parameterCount++;
-            } else if (child->AsElement()->GetAttr(kNameSpaceID_None,
-                                                   nsGkAtoms::index,
-                                                   indexValue)) {
+            }
+            else if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::index, indexValue)) {
                 PR_sscanf(NS_ConvertUTF16toUTF8(indexValue).get(),"%d",&index);
                 if (index > 0)
                     index--;
             }
             else {
                 parameterCount++;
             }
 
-            static Element::AttrValuesArray sTypeValues[] =
+            static nsIContent::AttrValuesArray sTypeValues[] =
                 { &nsGkAtoms::int32, &nsGkAtoms::integer, &nsGkAtoms::int64,
                   &nsGkAtoms::null, &nsGkAtoms::double_, &nsGkAtoms::string, nullptr };
 
             int32_t typeError = 1;
-            int32_t typeValue = child->AsElement()->
-              FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, sTypeValues,
-                              eCaseMatters);
+            int32_t typeValue = child->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type,
+                                                       sTypeValues, eCaseMatters);
             rv = NS_ERROR_ILLEGAL_VALUE;
             int32_t valInt32 = 0;
             int64_t valInt64 = 0;
             double valFloat = 0;
 
             switch (typeValue) {
               case 0:
               case 1:
@@ -363,17 +359,17 @@ nsXULTemplateQueryProcessorStorage::Comp
                 rv = statement->BindNullByIndex(index);
                 break;
               case 4:
                 typeError = PR_sscanf(NS_ConvertUTF16toUTF8(value).get(),"%lf",&valFloat);
                 if (typeError > 0)
                     rv = statement->BindDoubleByIndex(index, valFloat);
                 break;
               case 5:
-              case Element::ATTR_MISSING:
+              case nsIContent::ATTR_MISSING:
                 rv = statement->BindStringByIndex(index, value);
                 break;
               default:
                 typeError = 0;
             }
 
             if (typeError <= 0) {
                 nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_WRONG_TYPE_QUERY_PARAMETER);
--- a/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp
@@ -229,19 +229,17 @@ nsXULTemplateQueryProcessorXML::CompileQ
                                              nsAtom* aMemberVariable,
                                              nsISupports** _retval)
 {
     *_retval = nullptr;
 
     nsCOMPtr<nsIContent> content = do_QueryInterface(aQueryNode);
 
     nsAutoString expr;
-    if (content->IsElement()) {
-      content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
-    }
+    content->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
 
     // if an expression is not specified, then the default is to
     // just take all of the children
     if (expr.IsEmpty())
         expr.Assign('*');
 
     ErrorResult rv;
     nsAutoPtr<XPathExpression> compiledexpr;
@@ -256,20 +254,20 @@ nsXULTemplateQueryProcessorXML::CompileQ
 
     for (nsIContent* condition = content->GetFirstChild();
          condition;
          condition = condition->GetNextSibling()) {
 
         if (condition->NodeInfo()->Equals(nsGkAtoms::assign,
                                           kNameSpaceID_XUL)) {
             nsAutoString var;
-            condition->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::var, var);
+            condition->GetAttr(kNameSpaceID_None, nsGkAtoms::var, var);
 
             nsAutoString expr;
-            condition->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
+            condition->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
 
             // ignore assignments without a variable or an expression
             if (!var.IsEmpty() && !expr.IsEmpty()) {
                 compiledexpr = CreateExpression(expr, condition, rv);
                 if (rv.Failed()) {
                     nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_ASSIGN_XPATH);
                     return rv.StealNSResult();
                 }
--- a/dom/xul/templates/nsXULTreeBuilder.cpp
+++ b/dom/xul/templates/nsXULTreeBuilder.cpp
@@ -304,17 +304,17 @@ void
 nsXULTreeBuilder::GetCellProperties(int32_t aRow, nsTreeColumn& aColumn,
                                     nsAString& aProperties, ErrorResult& aError)
 {
     if (!IsValidRowIndex(aRow)) {
         aError.Throw(NS_ERROR_INVALID_ARG);
         return;
     }
 
-    Element* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
     if (cell) {
         nsAutoString raw;
         cell->GetAttr(kNameSpaceID_None, nsGkAtoms::properties, raw);
 
         if (!raw.IsEmpty()) {
             SubstituteText(mRows[aRow]->mMatch->mResult, raw, aProperties);
         }
     }
@@ -546,17 +546,17 @@ nsXULTreeBuilder::GetImageSrc(int32_t aR
                               nsAString& aSrc, ErrorResult& aError)
 {
     if (!IsValidRowIndex(aRow)) {
         aError.Throw(NS_ERROR_INVALID_ARG);
         return;
     }
 
     // Find the <cell> that corresponds to the column we want.
-    Element* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
     if (cell) {
         nsAutoString raw;
         cell->GetAttr(kNameSpaceID_None, nsGkAtoms::src, raw);
 
         SubstituteText(mRows[aRow]->mMatch->mResult, raw, aSrc);
     } else {
         aSrc.Truncate();
     }
@@ -578,17 +578,17 @@ nsXULTreeBuilder::GetProgressMode(int32_
                                   ErrorResult& aError)
 {
     if (!IsValidRowIndex(aRow)) {
         aError.Throw(NS_ERROR_INVALID_ARG);
         return -1;
     }
 
     // Find the <cell> that corresponds to the column we want.
-    Element* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
     if (cell) {
         nsAutoString raw;
         cell->GetAttr(kNameSpaceID_None, nsGkAtoms::mode, raw);
 
         nsAutoString mode;
         SubstituteText(mRows[aRow]->mMatch->mResult, raw, mode);
 
         if (mode.EqualsLiteral("normal")) {
@@ -619,17 +619,17 @@ nsXULTreeBuilder::GetCellValue(int32_t a
                                nsAString& aValue, ErrorResult& aError)
 {
     if (!IsValidRowIndex(aRow)) {
         aError.Throw(NS_ERROR_INVALID_ARG);
         return;
     }
 
     // Find the <cell> that corresponds to the column we want.
-    Element* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
     if (cell) {
         nsAutoString raw;
         cell->GetAttr(kNameSpaceID_None, nsGkAtoms::value, raw);
 
         SubstituteText(mRows[aRow]->mMatch->mResult, raw, aValue);
     } else {
         aValue.Truncate();
     }
@@ -651,17 +651,17 @@ nsXULTreeBuilder::GetCellText(int32_t aR
                               nsAString& aText, ErrorResult& aError)
 {
     if (!IsValidRowIndex(aRow)) {
         aError.Throw(NS_ERROR_INVALID_ARG);
         return;
     }
 
     // Find the <cell> that corresponds to the column we want.
-    Element* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
     if (cell) {
         nsAutoString raw;
         cell->GetAttr(kNameSpaceID_None, nsGkAtoms::label, raw);
 
         SubstituteText(mRows[aRow]->mMatch->mResult, raw, aText);
     } else {
         aText.Truncate();
     }
@@ -864,17 +864,17 @@ nsXULTreeBuilder::IsEditable(int32_t aRo
                              ErrorResult& aError)
 {
     if (!IsValidRowIndex(aRow)) {
         aError.Throw(NS_ERROR_INVALID_ARG);
         return false;
     }
 
     // Find the <cell> that corresponds to the column we want.
-    Element* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
     if (!cell) {
         return true;
     }
 
     nsAutoString raw;
     cell->GetAttr(kNameSpaceID_None, nsGkAtoms::editable, raw);
 
     nsAutoString editable;
@@ -899,17 +899,17 @@ nsXULTreeBuilder::IsSelectable(int32_t a
                                ErrorResult& aError)
 {
     if (!IsValidRowIndex(aRow)) {
         aError.Throw(NS_ERROR_INVALID_ARG);
         return false;
     }
 
     // Find the <cell> that corresponds to the column we want.
-    Element* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
     if (!cell) {
         return true;
     }
 
     nsAutoString raw;
     cell->GetAttr(kNameSpaceID_None, nsGkAtoms::selectable, raw);
 
     nsAutoString selectable;
@@ -1260,29 +1260,28 @@ nsXULTreeBuilder::EnsureSortVariables()
         return NS_OK;
 
     for (nsIContent* child = treecols->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
 
         if (child->NodeInfo()->Equals(nsGkAtoms::treecol,
                                       kNameSpaceID_XUL)) {
-            if (child->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                nsGkAtoms::sortActive,
-                                                nsGkAtoms::_true, eCaseMatters)) {
+            if (child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::sortActive,
+                                   nsGkAtoms::_true, eCaseMatters)) {
                 nsAutoString sort;
-                child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, sort);
+                child->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, sort);
                 if (! sort.IsEmpty()) {
                     mSortVariable = NS_Atomize(sort);
 
-                    static Element::AttrValuesArray strings[] =
+                    static nsIContent::AttrValuesArray strings[] =
                       {&nsGkAtoms::ascending, &nsGkAtoms::descending, nullptr};
-                    switch (child->AsElement()->FindAttrValueIn(kNameSpaceID_None,
-                                                                nsGkAtoms::sortDirection,
-                                                                strings, eCaseMatters)) {
+                    switch (child->FindAttrValueIn(kNameSpaceID_None,
+                                                   nsGkAtoms::sortDirection,
+                                                   strings, eCaseMatters)) {
                        case 0: mSortDirection = eDirection_Ascending; break;
                        case 1: mSortDirection = eDirection_Descending; break;
                        default: mSortDirection = eDirection_Natural; break;
                     }
                 }
                 break;
             }
         }
@@ -1376,43 +1375,42 @@ nsXULTreeBuilder::GetTemplateActionRowFo
             }
         }
     }
 
     *aResult = nullptr;
     return NS_OK;
 }
 
-Element*
+nsIContent*
 nsXULTreeBuilder::GetTemplateActionCellFor(int32_t aRow, nsTreeColumn& aCol)
 {
     RefPtr<Element> row;
     GetTemplateActionRowFor(aRow, getter_AddRefs(row));
     if (!row) {
         return nullptr;
     }
 
     RefPtr<nsAtom> colAtom(aCol.GetAtom());
     int32_t colIndex(aCol.GetIndex());
 
-    Element* result = nullptr;
+    nsIContent* result = nullptr;
     uint32_t j = 0;
     for (nsIContent* child = row->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
         if (child->NodeInfo()->Equals(nsGkAtoms::treecell, kNameSpaceID_XUL)) {
             if (colAtom &&
-                child->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                nsGkAtoms::ref, colAtom,
-                                                eCaseMatters)) {
-                return child->AsElement();
+                child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::ref, colAtom,
+                                   eCaseMatters)) {
+                return child;
             }
 
             if (j == (uint32_t)colIndex) {
-                result = child->AsElement();
+                result = child;
             }
             ++j;
         }
     }
     return result;
 }
 
 nsresult
--- a/dom/xul/templates/nsXULTreeBuilder.h
+++ b/dom/xul/templates/nsXULTreeBuilder.h
@@ -162,17 +162,17 @@ protected:
      */
     nsresult
     GetTemplateActionRowFor(int32_t aRow, mozilla::dom::Element** aResult);
 
     /**
      * Given a row and a column ID, use the row's match to figure out
      * the appropriate <treecell> in the rule's <action>.
      */
-    mozilla::dom::Element*
+    nsIContent*
     GetTemplateActionCellFor(int32_t aRow, nsTreeColumn& aCol);
 
     /**
      * Return the resource corresponding to a row in the tree.
      */
     nsresult
     GetResourceFor(int32_t aRow, nsIRDFResource** aResource);
 
--- a/editor/composer/nsComposeTxtSrvFilter.cpp
+++ b/editor/composer/nsComposeTxtSrvFilter.cpp
@@ -5,17 +5,16 @@
 
 #include "nsComposeTxtSrvFilter.h"
 #include "nsError.h"                    // for NS_OK
 #include "nsIContent.h"                 // for nsIContent
 #include "nsIDOMNode.h"                 // for nsIDOMNode
 #include "nsNameSpaceManager.h"        // for kNameSpaceID_None
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
 #include "nscore.h"                     // for NS_IMETHODIMP
-#include "mozilla/dom/Element.h"                 // for nsIContent
 
 nsComposeTxtSrvFilter::nsComposeTxtSrvFilter() :
   mIsForMail(false)
 {
 }
 
 NS_IMPL_ISUPPORTS(nsComposeTxtSrvFilter, nsITextServicesFilter)
 
@@ -26,45 +25,38 @@ nsComposeTxtSrvFilter::Skip(nsIDOMNode* 
 
   // Check to see if we can skip this node
   // For nodes that are blockquotes, we must make sure
   // their type is "cite"
   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
   if (content) {
     if (content->IsHTMLElement(nsGkAtoms::blockquote)) {
       if (mIsForMail) {
-        *_retval = content->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                     nsGkAtoms::type,
-                                                     nsGkAtoms::cite,
-                                                     eIgnoreCase);
+        *_retval = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                                        nsGkAtoms::cite, eIgnoreCase);
       }
     } else if (content->IsHTMLElement(nsGkAtoms::span)) {
       if (mIsForMail) {
-        *_retval = content->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                     nsGkAtoms::mozquote,
-                                                     nsGkAtoms::_true,
-                                                     eIgnoreCase);
+        *_retval = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozquote,
+                                        nsGkAtoms::_true, eIgnoreCase);
         if (!*_retval) {
-          *_retval = content->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                       nsGkAtoms::_class,
-                                                       nsGkAtoms::mozsignature,
-                                                       eCaseMatters);
+          *_retval = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::_class,
+                                          nsGkAtoms::mozsignature, eCaseMatters);
         }
       }
     } else if (content->IsAnyOfHTMLElements(nsGkAtoms::script,
                                             nsGkAtoms::textarea,
                                             nsGkAtoms::select,
                                             nsGkAtoms::style,
                                             nsGkAtoms::map)) {
       *_retval = true;
     } else if (content->IsHTMLElement(nsGkAtoms::table)) {
       if (mIsForMail) {
         *_retval =
-          content->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                            nsGkAtoms::_class,
-                                            NS_LITERAL_STRING("moz-email-headers-table"),
-                                            eCaseMatters);
+          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::_class,
+                               NS_LITERAL_STRING("moz-email-headers-table"),
+                               eCaseMatters);
       }
     }
   }
 
   return NS_OK;
 }
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -707,22 +707,18 @@ HTMLEditor::RemoveStyleInside(nsIContent
        (aProperty == nsGkAtoms::href && HTMLEditUtils::IsLink(&aNode)) ||
        // and for named anchors
        (aProperty == nsGkAtoms::name && HTMLEditUtils::IsNamedAnchor(&aNode)) ||
        // or node is any prop and we asked for that
        (!aProperty && NodeIsProperty(aNode)))) {
     // if we weren't passed an attribute, then we want to
     // remove any matching inlinestyles entirely
     if (!aAttribute || aAttribute->IsEmpty()) {
-      bool hasStyleAttr =
-        aNode.IsElement() &&
-        aNode.AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::style);
-      bool hasClassAttr =
-        aNode.IsElement() &&
-        aNode.AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::_class);
+      bool hasStyleAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::style);
+      bool hasClassAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::_class);
       if (aProperty && (hasStyleAttr || hasClassAttr)) {
         // aNode carries inline styles or a class attribute so we can't
         // just remove the element... We need to create above the element
         // a span that will carry those styles or class, then we can delete
         // the node.
         RefPtr<Element> spanNode =
           InsertContainerAbove(&aNode, nsGkAtoms::span);
         NS_ENSURE_STATE(spanNode);
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -278,27 +278,25 @@ TextEditor::UpdateMetaCharset(nsIDocumen
     nsCOMPtr<nsIContent> metaNode = metaList->Item(i);
     MOZ_ASSERT(metaNode);
 
     if (!metaNode->IsElement()) {
       continue;
     }
 
     nsAutoString currentValue;
-    metaNode->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv,
-                                   currentValue);
+    metaNode->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, currentValue);
 
     if (!FindInReadable(NS_LITERAL_STRING("content-type"),
                         currentValue,
                         nsCaseInsensitiveStringComparator())) {
       continue;
     }
 
-    metaNode->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::content,
-                                   currentValue);
+    metaNode->GetAttr(kNameSpaceID_None, nsGkAtoms::content, currentValue);
 
     NS_NAMED_LITERAL_STRING(charsetEquals, "charset=");
     nsAString::const_iterator originalStart, start, end;
     originalStart = currentValue.BeginReading(start);
     currentValue.EndReading(end);
     if (!FindInReadable(charsetEquals, start, end,
                         nsCaseInsensitiveStringComparator())) {
       continue;
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -1247,27 +1247,27 @@ mozInlineSpellChecker::ShouldSpellCheckN
     return false;
 
   nsIContent *content = aNode->AsContent();
 
   if (aTextEditor->IsMailEditor()) {
     nsIContent *parent = content->GetParent();
     while (parent) {
       if (parent->IsHTMLElement(nsGkAtoms::blockquote) &&
-          parent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::type,
-                                           nsGkAtoms::cite,
-                                           eIgnoreCase)) {
+          parent->AttrValueIs(kNameSpaceID_None,
+                              nsGkAtoms::type,
+                              nsGkAtoms::cite,
+                              eIgnoreCase)) {
         return false;
       }
       if (parent->IsHTMLElement(nsGkAtoms::pre) &&
-          parent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::_class,
-                                           nsGkAtoms::mozsignature,
-                                           eIgnoreCase)) {
+          parent->AttrValueIs(kNameSpaceID_None,
+                              nsGkAtoms::_class,
+                              nsGkAtoms::mozsignature,
+                              eIgnoreCase)) {
         return false;
       }
 
       parent = parent->GetParent();
     }
   } else {
     // Check spelling only if the node is editable, and GetSpellcheck() is true
     // on the nearest HTMLElement ancestor.
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -177,18 +177,17 @@ HasTouchListener(nsIContent* aContent)
 }
 
 static bool
 IsDescendant(nsIFrame* aFrame, nsIContent* aAncestor, nsAutoString* aLabelTargetId)
 {
   for (nsIContent* content = aFrame->GetContent(); content;
        content = content->GetFlattenedTreeParent()) {
     if (aLabelTargetId && content->IsHTMLElement(nsGkAtoms::label)) {
-      content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::_for,
-                                    *aLabelTargetId);
+      content->GetAttr(kNameSpaceID_None, nsGkAtoms::_for, *aLabelTargetId);
     }
     if (content == aAncestor) {
       return true;
     }
   }
   return false;
 }
 
@@ -208,30 +207,29 @@ GetClickableAncestor(nsIFrame* aFrame, n
     if (content->IsAnyOfHTMLElements(nsGkAtoms::button,
                                      nsGkAtoms::input,
                                      nsGkAtoms::select,
                                      nsGkAtoms::textarea)) {
       return content;
     }
     if (content->IsHTMLElement(nsGkAtoms::label)) {
       if (aLabelTargetId) {
-        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::_for,
-                                      *aLabelTargetId);
+        content->GetAttr(kNameSpaceID_None, nsGkAtoms::_for, *aLabelTargetId);
       }
       return content;
     }
 
     // Bug 921928: we don't have access to the content of remote iframe.
     // So fluffing won't go there. We do an optimistic assumption here:
     // that the content of the remote iframe needs to be a target.
     if (content->IsHTMLElement(nsGkAtoms::iframe) &&
-        content->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozbrowser,
-                                          nsGkAtoms::_true, eIgnoreCase) &&
-        content->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
-                                          nsGkAtoms::_true, eIgnoreCase)) {
+        content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozbrowser,
+                             nsGkAtoms::_true, eIgnoreCase) &&
+        content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
+                             nsGkAtoms::_true, eIgnoreCase)) {
       return content;
     }
 
     // See nsCSSFrameConstructor::FindXULTagData. This code is not
     // really intended to be used with XUL, though.
     if (content->IsAnyOfXULElements(nsGkAtoms::button,
                                     nsGkAtoms::checkbox,
                                     nsGkAtoms::radio,
@@ -240,21 +238,20 @@ GetClickableAncestor(nsIFrame* aFrame, n
                                     nsGkAtoms::menubutton,
                                     nsGkAtoms::menuitem,
                                     nsGkAtoms::menulist,
                                     nsGkAtoms::scrollbarbutton,
                                     nsGkAtoms::resizer)) {
       return content;
     }
 
-    static Element::AttrValuesArray clickableRoles[] =
+    static nsIContent::AttrValuesArray clickableRoles[] =
       { &nsGkAtoms::button, &nsGkAtoms::key, nullptr };
-    if (content->IsElement() &&
-        content->AsElement()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::role,
-                                              clickableRoles, eIgnoreCase) >= 0) {
+    if (content->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::role,
+                                 clickableRoles, eIgnoreCase) >= 0) {
       return content;
     }
     if (content->IsEditable()) {
       return content;
     }
     nsCOMPtr<nsIURI> linkURI;
     if (content->IsLink(getter_AddRefs(linkURI))) {
       return content;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1729,17 +1729,17 @@ nsCSSFrameConstructor::CreateGenConTextN
                          nsINode::DeleteProperty<nsGenConInitializer>);
     aState.mGeneratedTextNodesWithInitializer.AppendObject(content);
   }
   return content.forget();
 }
 
 already_AddRefed<nsIContent>
 nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
-                                              Element* aParentContent,
+                                              nsIContent*     aParentContent,
                                               nsStyleContext* aStyleContext,
                                               uint32_t        aContentIndex)
 {
   // Get the content value
   const nsStyleContentData &data =
     aStyleContext->StyleContent()->ContentAt(aContentIndex);
   nsStyleContentType type = data.GetType();
 
@@ -1846,17 +1846,18 @@ nsCSSFrameConstructor::CreateGeneratedCo
       // detect that and do the right thing here?
       if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::alt)) {
         nsCOMPtr<nsIContent> content;
         NS_NewAttributeContent(mDocument->NodeInfoManager(),
                                kNameSpaceID_None, nsGkAtoms::alt, getter_AddRefs(content));
         return content.forget();
       }
 
-      if (aParentContent->IsHTMLElement(nsGkAtoms::input)) {
+      if (aParentContent->IsHTMLElement() &&
+          aParentContent->NodeInfo()->Equals(nsGkAtoms::input)) {
         if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
           nsCOMPtr<nsIContent> content;
           NS_NewAttributeContent(mDocument->NodeInfoManager(),
                                  kNameSpaceID_None, nsGkAtoms::value, getter_AddRefs(content));
           return content.forget();
         }
 
         nsAutoString temp;
@@ -1889,31 +1890,33 @@ nsCSSFrameConstructor::CreateGeneratedCo
  * children of the XML element. Then we create a frame subtree for
  * the XML element as if it were a regular child of
  * aParentFrame/aParentContent, giving the XML element the ::before or
  * ::after style.
  */
 void
 nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aState,
                                                   nsContainerFrame* aParentFrame,
-                                                  Element* aParentContent,
+                                                  nsIContent*      aParentContent,
                                                   nsStyleContext*  aStyleContext,
                                                   CSSPseudoElementType aPseudoElement,
                                                   FrameConstructionItemList& aItems)
 {
   MOZ_ASSERT(aPseudoElement == CSSPseudoElementType::before ||
              aPseudoElement == CSSPseudoElementType::after,
              "unexpected aPseudoElement");
 
+  MOZ_ASSERT(aParentContent->IsElement());
+
   StyleSetHandle styleSet = mPresShell->StyleSet();
 
   // Probe for the existence of the pseudo-element
   RefPtr<nsStyleContext> pseudoStyleContext;
   pseudoStyleContext =
-    styleSet->ProbePseudoElementStyle(aParentContent,
+    styleSet->ProbePseudoElementStyle(aParentContent->AsElement(),
                                       aPseudoElement,
                                       aStyleContext,
                                       aState.mTreeMatchContext);
   if (!pseudoStyleContext)
     return;
 
   bool isBefore = aPseudoElement == CSSPseudoElementType::before;
 
@@ -4219,18 +4222,18 @@ nsCSSFrameConstructor::ConstructFrameFro
       newFrameAsContainer->SetInitialChildList(kPrincipalList, childItems);
     }
   }
 
 #ifdef MOZ_XUL
   // More icky XUL stuff
   if (aItem.mNameSpaceID == kNameSpaceID_XUL &&
       (aItem.mTag == nsGkAtoms::treechildren || // trees always need titletips
-       content->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext) ||
-       content->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltip))) {
+       content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext) ||
+       content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltip))) {
     nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
     if (rootBox) {
       rootBox->AddTooltipSupport(content);
     }
   }
 #endif
 
   NS_ASSERTION(newFrame->IsFrameOfType(nsIFrame::eLineParticipant) ==
@@ -6098,19 +6101,18 @@ nsCSSFrameConstructor::AddFrameConstruct
       ancestorPusher.PushAncestorAndStyleScope(aContent->AsElement());
     } else {
       ancestorPusher.PushStyleScope(aContent->AsElement());
     }
 
     if (aParentFrame) {
       aParentFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
     }
-    CreateGeneratedContentItem(aState, aParentFrame, aContent->AsElement(),
-                               styleContext, CSSPseudoElementType::before,
-                               aItems);
+    CreateGeneratedContentItem(aState, aParentFrame, aContent, styleContext,
+                               CSSPseudoElementType::before, aItems);
 
     FlattenedChildIterator iter(aContent);
     for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
       if (!ShouldCreateItemsForChild(aState, child, aParentFrame)) {
         continue;
       }
 
       // Get the parent of the content and check if it is a XBL children element
@@ -6132,19 +6134,18 @@ nsCSSFrameConstructor::AddFrameConstruct
       RefPtr<nsStyleContext> childContext =
         ResolveStyleContext(styleContext, child, &aState);
       DoAddFrameConstructionItems(aState, child, childContext,
                                   aSuppressWhiteSpaceOptimizations,
                                   aParentFrame, aAnonChildren, aItems);
     }
     aItems.SetParentHasNoXBLChildren(!iter.XBLInvolved());
 
-    CreateGeneratedContentItem(aState, aParentFrame, aContent->AsElement(),
-                               styleContext, CSSPseudoElementType::after,
-                               aItems);
+    CreateGeneratedContentItem(aState, aParentFrame, aContent, styleContext,
+                               CSSPseudoElementType::after, aItems);
     if (canHavePageBreak && display->mBreakAfter) {
       AddPageBreakItem(aContent, aItems);
     }
     return;
   }
 
   FrameConstructionItem* item = nullptr;
   if (details && details->Open()) {
@@ -8901,30 +8902,30 @@ nsCSSFrameConstructor::WillDestroyFrameT
   nsFrameManager::Destroy();
 }
 
 //STATIC
 
 // XXXbz I'd really like this method to go away. Once we have inline-block and
 // I can just use that for sized broken images, that can happen, maybe.
 void
-nsCSSFrameConstructor::GetAlternateTextFor(Element* aElement,
+nsCSSFrameConstructor::GetAlternateTextFor(nsIContent* aContent,
                                            nsAtom* aTag,
                                            nsAString& aAltText)
 {
   // The "alt" attribute specifies alternate text that is rendered
   // when the image can not be displayed.
-  if (aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aAltText)) {
+  if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aAltText)) {
     return;
   }
 
   if (nsGkAtoms::input == aTag) {
     // If there's no "alt" attribute, and aContent is an input element, then use
     // the value of the "value" attribute
-    if (aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aAltText)) {
+    if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aAltText)) {
       return;
     }
 
     // If there's no "value" attribute either, then use the localized string for
     // "Submit" as the alternate text.
     nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
                                        "Submit", aAltText);
   }
@@ -11051,18 +11052,18 @@ nsCSSFrameConstructor::ProcessChildren(n
     // it has nothing to do with the parent frame's desired behavior.
     nsStyleContext* styleContext;
 
     if (aCanHaveGeneratedContent) {
       aFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
       styleContext =
         nsFrame::CorrectStyleParentFrame(aFrame, nullptr)->StyleContext();
       // Probe for generated content before
-      CreateGeneratedContentItem(aState, aFrame, aContent->AsElement(),
-                                 styleContext, CSSPseudoElementType::before,
+      CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
+                                 CSSPseudoElementType::before,
                                  itemsToConstruct);
     }
 
     const bool addChildItems = MOZ_LIKELY(mCurrentDepth < kMaxDepth);
     if (!addChildItems) {
       NS_WARNING("ProcessChildren max depth exceeded");
     }
 
@@ -11106,18 +11107,18 @@ nsCSSFrameConstructor::ProcessChildren(n
       } else {
         ClearLazyBits(child, child->GetNextSibling());
       }
     }
     itemsToConstruct.SetParentHasNoXBLChildren(!iter.XBLInvolved());
 
     if (aCanHaveGeneratedContent) {
       // Probe for generated content after
-      CreateGeneratedContentItem(aState, aFrame, aContent->AsElement(),
-                                 styleContext, CSSPseudoElementType::after,
+      CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
+                                 CSSPseudoElementType::after,
                                  itemsToConstruct);
     }
   } else {
     ClearLazyBits(aContent->GetFirstChild(), nullptr);
   }
 
   ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
                               /* aParentIsWrapperAnonBox = */ false,
@@ -12288,18 +12289,18 @@ nsCSSFrameConstructor::BuildInlineChildI
   if (aState.HasAncestorFilter()) {
     ancestorPusher.PushAncestorAndStyleScope(parentContent->AsElement());
   } else {
     ancestorPusher.PushStyleScope(parentContent->AsElement());
   }
 
   if (!aItemIsWithinSVGText) {
     // Probe for generated content before
-    CreateGeneratedContentItem(aState, nullptr, parentContent->AsElement(),
-                               parentStyleContext, CSSPseudoElementType::before,
+    CreateGeneratedContentItem(aState, nullptr, parentContent, parentStyleContext,
+                               CSSPseudoElementType::before,
                                aParentItem.mChildItems);
   }
 
   uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK;
   if (aItemIsWithinSVGText) {
     flags |= ITEM_IS_WITHIN_SVG_TEXT;
   }
   if (aItemAllowsTextPathChild && aParentItem.mIsForSVGAElement) {
@@ -12357,18 +12358,17 @@ nsCSSFrameConstructor::BuildInlineChildI
                                         iter.XBLInvolved(), childContext,
                                         flags, nullptr,
                                         aParentItem.mChildItems);
     }
   }
 
   if (!aItemIsWithinSVGText) {
     // Probe for generated content after
-    CreateGeneratedContentItem(aState, nullptr, parentContent->AsElement(),
-                               parentStyleContext,
+    CreateGeneratedContentItem(aState, nullptr, parentContent, parentStyleContext,
                                CSSPseudoElementType::after,
                                aParentItem.mChildItems);
   }
 
   aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
 }
 
 // return whether it's ok to append (in the AppendFrames sense) to
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -62,17 +62,17 @@ public:
 
   nsCSSFrameConstructor(nsIDocument* aDocument, nsIPresShell* aPresShell);
   ~nsCSSFrameConstructor() {
     MOZ_ASSERT(mUpdateCount == 0, "Dying in the middle of our own update?");
     MOZ_ASSERT(mFCItemsInUse == 0);
   }
 
   // get the alternate text for a content node
-  static void GetAlternateTextFor(mozilla::dom::Element* aContent,
+  static void GetAlternateTextFor(nsIContent* aContent,
                                   nsAtom* aTag,  // content object's tag
                                   nsAString& aAltText);
 
 private:
   nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) = delete;
   nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) = delete;
 
 public:
@@ -465,17 +465,17 @@ private:
    * @param aAttrNamespace the namespace of the attribute in question
    * @param aAttrName the localname of the attribute
    * @param aStyleContext the style context to use
    * @param aGeneratedContent the array of generated content to append the
    *                          created content to.
    * @param [out] aNewContent the content node we create
    * @param [out] aNewFrame the new frame we create
    */
-  void CreateAttributeContent(mozilla::dom::Element* aParentContent,
+  void CreateAttributeContent(nsIContent* aParentContent,
                               nsIFrame* aParentFrame,
                               int32_t aAttrNamespace,
                               nsAtom* aAttrName,
                               nsStyleContext* aStyleContext,
                               nsCOMArray<nsIContent>& aGeneratedContent,
                               nsIContent** aNewContent,
                               nsIFrame** aNewFrame);
 
@@ -493,24 +493,24 @@ private:
    * The caller takes care of making it SetIsNativeAnonymousRoot, binding it
    * to the document, and creating frames for it.
    * @param aParentContent is the node that has the before/after style
    * @param aStyleContext is the 'before' or 'after' pseudo-element
    * style context
    * @param aContentIndex is the index of the content item to create
    */
   already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState,
-                                                      mozilla::dom::Element* aParentContent,
+                                                      nsIContent*     aParentContent,
                                                       nsStyleContext* aStyleContext,
                                                       uint32_t        aContentIndex);
 
   // aFrame may be null; this method doesn't use it directly in any case.
   void CreateGeneratedContentItem(nsFrameConstructorState&   aState,
                                   nsContainerFrame*          aFrame,
-                                  mozilla::dom::Element*     aContent,
+                                  nsIContent*                aContent,
                                   nsStyleContext*            aStyleContext,
                                   CSSPseudoElementType       aPseudoElement,
                                   FrameConstructionItemList& aItems);
 
   // This method can change aFrameList: it can chop off the beginning and put
   // it in aParentFrame while putting the remainder into a ib-split sibling of
   // aParentFrame.  aPrevSibling must be the frame after which aFrameList is to
   // be placed on aParentFrame's principal child list.  It may be null if
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -7891,17 +7891,17 @@ nsLayoutUtils::SurfaceFromElement(dom::E
   if (!imageLoader) {
     return SurfaceFromElementResult();
   }
 
   return SurfaceFromElement(imageLoader, aSurfaceFlags, aTarget);
 }
 
 /* static */
-Element*
+nsIContent*
 nsLayoutUtils::GetEditableRootContentByContentEditable(nsIDocument* aDocument)
 {
   // If the document is in designMode we should return nullptr.
   if (!aDocument || aDocument->HasFlag(NODE_IS_EDITABLE)) {
     return nullptr;
   }
 
   // contenteditable only works with HTML document.
@@ -7917,17 +7917,17 @@ nsLayoutUtils::GetEditableRootContentByC
   if (rootElement && rootElement->IsEditable()) {
     return rootElement;
   }
 
   // If there are no editable root element, check its <body> element.
   // Note that the body element could be <frameset> element.
   nsCOMPtr<nsIDOMHTMLElement> body;
   nsresult rv = domHTMLDoc->GetBody(getter_AddRefs(body));
-  nsCOMPtr<Element> content = do_QueryInterface(body);
+  nsCOMPtr<nsIContent> content = do_QueryInterface(body);
   if (NS_SUCCEEDED(rv) && content && content->IsEditable()) {
     return content;
   }
   return nullptr;
 }
 
 #ifdef DEBUG
 /* static */ void
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -2246,18 +2246,18 @@ public:
    *  <body contenteditable="true"></body>
    *    With these cases, this returns the <body>.
    *    NOTE: The latter case isn't created normally, however, it can be
    *          created by script with XHTML.
    *
    *  <body><p contenteditable="true"></p></body>
    *    returns nullptr because <body> isn't editable.
    */
-  static mozilla::dom::Element*
-  GetEditableRootContentByContentEditable(nsIDocument* aDocument);
+  static nsIContent*
+    GetEditableRootContentByContentEditable(nsIDocument* aDocument);
 
   static void AddExtraBackgroundItems(nsDisplayListBuilder& aBuilder,
                                       nsDisplayList& aList,
                                       nsIFrame* aFrame,
                                       const nsRect& aCanvasArea,
                                       const nsRegion& aVisibleRegion,
                                       nscolor aBackstop);
 
--- a/layout/forms/nsCheckboxRadioFrame.cpp
+++ b/layout/forms/nsCheckboxRadioFrame.cpp
@@ -156,17 +156,17 @@ nsCheckboxRadioFrame::RegUnRegAccessKey(
   NS_ENSURE_ARG_POINTER(aFrame);
 
   nsPresContext* presContext = aFrame->PresContext();
 
   NS_ASSERTION(presContext, "aPresContext is NULL in RegUnRegAccessKey!");
 
   nsAutoString accessKey;
 
-  Element* content = aFrame->GetContent()->AsElement();
+  nsIContent* content = aFrame->GetContent();
   content->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
   if (!accessKey.IsEmpty()) {
     EventStateManager* stateManager = presContext->EventStateManager();
     if (aDoReg) {
       stateManager->RegisterAccessKey(content, (uint32_t)accessKey.First());
     } else {
       stateManager->UnregisterAccessKey(content, (uint32_t)accessKey.First());
     }
--- a/layout/forms/nsDateTimeControlFrame.cpp
+++ b/layout/forms/nsDateTimeControlFrame.cpp
@@ -339,28 +339,24 @@ nsDateTimeControlFrame::CreateAnonymousC
   NS_TrustedNewXULElement(getter_AddRefs(mInputAreaContent), nodeInfo.forget());
   aElements.AppendElement(mInputAreaContent);
 
   nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
     do_QueryInterface(mInputAreaContent);
   if (inputAreaContent) {
     // Propogate our tabindex.
     nsAutoString tabIndexStr;
-    if (mContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                       nsGkAtoms::tabindex,
-                                       tabIndexStr)) {
+    if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr)) {
       inputAreaContent->SetEditAttribute(NS_LITERAL_STRING("tabindex"),
                                          tabIndexStr);
     }
 
     // Propagate our readonly state.
     nsAutoString readonly;
-    if (mContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                       nsGkAtoms::readonly,
-                                       readonly)) {
+    if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly)) {
       inputAreaContent->SetEditAttribute(NS_LITERAL_STRING("readonly"),
                                          readonly);
     }
 
     SyncDisabledState();
   }
 
   return NS_OK;
@@ -428,17 +424,17 @@ nsDateTimeControlFrame::AttributeChanged
               inputAreaContent->RemoveEditAttribute(name);
             }
           } else {
             MOZ_ASSERT(aModType == nsIDOMMutationEvent::ADDITION ||
                        aModType == nsIDOMMutationEvent::MODIFICATION);
             if (inputAreaContent) {
               nsAtomString name(aAttribute);
               nsAutoString value;
-              contentAsInputElem->GetAttr(aNameSpaceID, aAttribute, value);
+              mContent->GetAttr(aNameSpaceID, aAttribute, value);
               inputAreaContent->SetEditAttribute(name, value);
             }
           }
         }
       }
     }
   }
 
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -252,20 +252,18 @@ nsFileControlFrame::DnDListener::HandleE
 
   nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
   dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
   if (!IsValidDropData(dataTransfer)) {
     return NS_OK;
   }
 
 
-  RefPtr<HTMLInputElement> inputElement =
-    HTMLInputElement::FromContent(mFrame->GetContent());
-  bool supportsMultiple =
-    inputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
+  nsCOMPtr<nsIContent> content = mFrame->GetContent();
+  bool supportsMultiple = content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
   if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) {
     dataTransfer->SetDropEffect(NS_LITERAL_STRING("none"));
     aEvent->StopPropagation();
     return NS_OK;
   }
 
   nsAutoString eventType;
   aEvent->GetType(eventType);
@@ -274,41 +272,46 @@ nsFileControlFrame::DnDListener::HandleE
     aEvent->PreventDefault();
     return NS_OK;
   }
 
   if (eventType.EqualsLiteral("drop")) {
     aEvent->StopPropagation();
     aEvent->PreventDefault();
 
+    NS_ASSERTION(content, "The frame has no content???");
+
+    HTMLInputElement* inputElement = HTMLInputElement::FromContent(content);
+    NS_ASSERTION(inputElement, "No input element for this file upload control frame!");
+
     nsCOMPtr<nsIDOMFileList> fileList;
     dataTransfer->GetFiles(getter_AddRefs(fileList));
 
     RefPtr<BlobImpl> webkitDir;
     nsresult rv =
       GetBlobImplForWebkitDirectory(fileList, getter_AddRefs(webkitDir));
     NS_ENSURE_SUCCESS(rv, NS_OK);
 
     nsTArray<OwningFileOrDirectory> array;
     if (webkitDir) {
-      AppendBlobImplAsDirectory(array, webkitDir, inputElement);
+      AppendBlobImplAsDirectory(array, webkitDir, content);
       inputElement->MozSetDndFilesAndDirectories(array);
     } else {
       bool blinkFileSystemEnabled =
         Preferences::GetBool("dom.webkitBlink.filesystem.enabled", false);
       bool dirPickerEnabled =
         Preferences::GetBool("dom.input.dirpicker", false);
       if (blinkFileSystemEnabled || dirPickerEnabled) {
         FileList* files = static_cast<FileList*>(fileList.get());
         if (files) {
           for (uint32_t i = 0; i < files->Length(); ++i) {
             File* file = files->Item(i);
             if (file) {
               if (file->Impl() && file->Impl()->IsDirectory()) {
-                AppendBlobImplAsDirectory(array, file->Impl(), inputElement);
+                AppendBlobImplAsDirectory(array, file->Impl(), content);
               } else {
                 OwningFileOrDirectory* element = array.AppendElement();
                 element->SetAsFile() = file;
               }
             }
           }
         }
       }
@@ -325,22 +328,20 @@ nsFileControlFrame::DnDListener::HandleE
       else if (dirPickerEnabled) {
         inputElement->SetFilesOrDirectories(array, true);
       }
       // Normal DnD
       else {
         inputElement->SetFiles(fileList, true);
       }
 
-      nsContentUtils::DispatchTrustedEvent(inputElement->OwnerDoc(),
-                                           static_cast<nsINode*>(inputElement),
+      nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
                                            NS_LITERAL_STRING("input"), true,
                                            false);
-      nsContentUtils::DispatchTrustedEvent(inputElement->OwnerDoc(),
-                                           static_cast<nsINode*>(inputElement),
+      nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
                                            NS_LITERAL_STRING("change"), true,
                                            false);
     }
   }
 
   return NS_OK;
 }
 
@@ -448,17 +449,17 @@ nsFileControlFrame::AttributeChanged(int
                                      nsAtom* aAttribute,
                                      int32_t  aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::tabindex) {
     if (aModType == nsIDOMMutationEvent::REMOVAL) {
       mBrowseFilesOrDirs->UnsetAttr(aNameSpaceID, aAttribute, true);
     } else {
       nsAutoString value;
-      mContent->AsElement()->GetAttr(aNameSpaceID, aAttribute, value);
+      mContent->GetAttr(aNameSpaceID, aAttribute, value);
       mBrowseFilesOrDirs->SetAttr(aNameSpaceID, aAttribute, value, true);
     }
   }
 
   return nsBlockFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 void
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -105,17 +105,17 @@ nsGfxButtonControlFrame::GetDefaultLabel
 }
 
 nsresult
 nsGfxButtonControlFrame::GetLabel(nsString& aLabel)
 {
   // Get the text from the "value" property on our content if there is
   // one; otherwise set it to a default value (localized).
   dom::HTMLInputElement* elt = dom::HTMLInputElement::FromContent(mContent);
-  if (elt && elt->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::value) && elt) {
     elt->GetValue(aLabel, dom::CallerType::System);
   } else {
     // Generate localized label.
     // We can't make any assumption as to what the default would be
     // because the value is localized for non-english platforms, thus
     // it might not be the string "Reset", "Submit Query", or "Browse..."
     nsresult rv;
     rv = GetDefaultLabel(aLabel);
--- a/layout/forms/nsImageControlFrame.cpp
+++ b/layout/forms/nsImageControlFrame.cpp
@@ -144,19 +144,17 @@ nsImageControlFrame::HandleEvent(nsPresC
   }
 
   // do we have user-input style?
   const nsStyleUserInterface* uiStyle = StyleUserInterface();
   if (uiStyle->mUserInput == StyleUserInput::None ||
       uiStyle->mUserInput == StyleUserInput::Disabled) {
     return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
   }
-
-  if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) {
-    // XXX cache disabled
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) { // XXX cache disabled
     return NS_OK;
   }
 
   *aEventStatus = nsEventStatus_eIgnore;
 
   if (aEvent->mMessage == eMouseUp &&
       aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
     // Store click point for HTMLInputElement::SubmitNamesValues
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -253,31 +253,31 @@ protected:
   HTMLOptionElement* GetNonDisabledOptionFrom(int32_t aFromIndex,
                                               int32_t* aFoundIndex = nullptr);
 
   /**
    * Updates the selected text in a combobox and then calls FireOnChange().
    * @note This method might destroy the frame, pres shell and other objects.
    * Returns false if calling it destroyed |this|.
    */
-  bool UpdateSelection();
+  bool       UpdateSelection();
 
   /**
    * Returns whether mContent supports multiple selection.
    */
-  bool GetMultiple() const {
-    return mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
+  bool       GetMultiple() const {
+    return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
   }
 
 
   /**
    * Toggles (show/hide) the combobox dropdown menu.
    * @note This method might destroy the frame, pres shell and other objects.
    */
-  void DropDownToggleKey(nsIDOMEvent* aKeyEvent);
+  void       DropDownToggleKey(nsIDOMEvent* aKeyEvent);
 
   nsresult   IsOptionDisabled(int32_t anIndex, bool &aIsDisabled);
   /**
    * @note This method might destroy the frame, pres shell and other objects.
    */
   void ScrollToFrame(HTMLOptionElement& aOptElement);
   /**
    * @note This method might destroy the frame, pres shell and other objects.
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -271,17 +271,17 @@ nsNumberControlFrame::AttributeChanged(i
         aAttribute == nsGkAtoms::readonly ||
         aAttribute == nsGkAtoms::tabindex) {
       if (aModType == nsIDOMMutationEvent::REMOVAL) {
         mTextField->UnsetAttr(aNameSpaceID, aAttribute, true);
       } else {
         MOZ_ASSERT(aModType == nsIDOMMutationEvent::ADDITION ||
                    aModType == nsIDOMMutationEvent::MODIFICATION);
         nsAutoString value;
-        mContent->AsElement()->GetAttr(aNameSpaceID, aAttribute, value);
+        mContent->GetAttr(aNameSpaceID, aAttribute, value);
         mTextField->SetAttr(aNameSpaceID, aAttribute, value, true);
       }
     }
   }
 
   return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
                                             aModType);
 }
@@ -393,29 +393,27 @@ nsNumberControlFrame::CreateAnonymousCon
 
   // Initialize the text field value:
   nsAutoString value;
   content->GetValue(value, CallerType::System);
   SetValueOfAnonTextControl(value);
 
   // If we're readonly, make sure our anonymous text control is too:
   nsAutoString readonly;
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::readonly,
-                                     readonly)) {
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly)) {
     mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly, false);
   }
 
   // Propogate our tabindex:
   IgnoredErrorResult ignored;
   textField->SetTabIndex(content->TabIndex(), ignored);
 
   // Initialize the text field's placeholder, if ours is set:
   nsAutoString placeholder;
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder,
-                                     placeholder)) {
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, placeholder)) {
     mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, placeholder, false);
   }
 
   if (mContent->AsElement()->State().HasState(NS_EVENT_STATE_FOCUS)) {
     // We don't want to focus the frame but the text field.
     RefPtr<FocusTextField> focusJob = new FocusTextField(mContent, mTextField);
     nsContentUtils::AddScriptRunner(focusJob);
   }
@@ -479,20 +477,18 @@ nsNumberControlFrame::GetNumberControlFr
   // have to check for this via the content tree because we don't know whether
   // extra frames will be wrapped around any of the elements between aFrame and
   // the nsNumberControlFrame that we're looking for (e.g. flex wrappers).
   nsIContent* content = aFrame->GetContent();
   if (content->IsInNativeAnonymousSubtree() &&
       content->GetParent() && content->GetParent()->GetParent()) {
     nsIContent* grandparent = content->GetParent()->GetParent();
     if (grandparent->IsHTMLElement(nsGkAtoms::input) &&
-        grandparent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                              nsGkAtoms::type,
-                                              nsGkAtoms::number,
-                                              eCaseMatters)) {
+        grandparent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                                 nsGkAtoms::number, eCaseMatters)) {
       return do_QueryFrame(grandparent->GetPrimaryFrame());
     }
   }
   return nullptr;
 }
 
 /* static */ nsNumberControlFrame*
 nsNumberControlFrame::GetNumberControlFrameForSpinButton(nsIFrame* aFrame)
@@ -503,20 +499,18 @@ nsNumberControlFrame::GetNumberControlFr
   // extra frames will be wrapped around any of the elements between aFrame and
   // the nsNumberControlFrame that we're looking for (e.g. flex wrappers).
   nsIContent* content = aFrame->GetContent();
   if (content->IsInNativeAnonymousSubtree() &&
       content->GetParent() && content->GetParent()->GetParent() &&
       content->GetParent()->GetParent()->GetParent()) {
     nsIContent* greatgrandparent = content->GetParent()->GetParent()->GetParent();
     if (greatgrandparent->IsHTMLElement(nsGkAtoms::input) &&
-        greatgrandparent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                   nsGkAtoms::type,
-                                                   nsGkAtoms::number,
-                                                   eCaseMatters)) {
+        greatgrandparent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                                      nsGkAtoms::number, eCaseMatters)) {
       return do_QueryFrame(greatgrandparent->GetPrimaryFrame());
     }
   }
   return nullptr;
 }
 
 int32_t
 nsNumberControlFrame::GetSpinButtonForPointerEvent(WidgetGUIEvent* aEvent) const
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -488,18 +488,17 @@ nsTextControlFrame::CreateRootNode()
 
 void
 nsTextControlFrame::CreatePlaceholderIfNeeded()
 {
   MOZ_ASSERT(!mPlaceholderDiv);
 
   // Do we need a placeholder node?
   nsAutoString placeholderTxt;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder,
-                                 placeholderTxt);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, placeholderTxt);
   if (IsTextArea()) { // <textarea>s preserve newlines...
     nsContentUtils::PlatformToDOMLineBreaks(placeholderTxt);
   } else { // ...<input>s don't
     nsContentUtils::RemoveNewlines(placeholderTxt);
   }
 
   if (placeholderTxt.IsEmpty()) {
     return;
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -3,17 +3,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/. */
 
 #ifndef nsTextControlFrame_h___
 #define nsTextControlFrame_h___
 
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/Element.h"
 #include "nsContainerFrame.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsIContent.h"
 #include "nsITextControlFrame.h"
 #include "nsITextControlElement.h"
 #include "nsIStatefulFrame.h"
 
 class nsISelectionController;
@@ -295,17 +294,17 @@ protected:
   bool GetMaxLength(int32_t* aMaxLength);
 
   /**
    * Find out whether an attribute exists on the content or not.
    * @param aAtt the attribute to determine the existence of
    * @returns false if it does not exist
    */
   bool AttributeExists(nsAtom *aAtt) const
-  { return mContent && mContent->AsElement()->HasAttr(kNameSpaceID_None, aAtt); }
+  { return mContent && mContent->HasAttr(kNameSpaceID_None, aAtt); }
 
   /**
    * We call this when we are being destroyed or removed from the PFM.
    * @param aPresContext the current pres context
    */
   void PreDestroy();
 
   // Compute our intrinsic size.  This does not include any borders, paddings,
--- a/layout/generic/BlockReflowInput.cpp
+++ b/layout/generic/BlockReflowInput.cpp
@@ -831,38 +831,33 @@ BlockReflowInput::FlowAndPlaceFloat(nsIF
       while (fc) {
         if (fc->mFloat == aFloat) {
           break;
         }
         prevFrame = fc->mFloat;
         fc = fc->Next();
       }
 
-      if (prevFrame) {
+      if(prevFrame) {
         //get the frame type
         if (prevFrame->IsTableWrapperFrame()) {
           //see if it has "align="
-          // IE makes a difference between align and the float property.
-          //
-          // We're interested only if previous frame is align=left IE messes
-          // things up when "right" (overlapping frames).
-          //
-          // FIXME(emilio, bug 1426747): This looks fishy.
+          // IE makes a difference between align and he float property
           nsIContent* content = prevFrame->GetContent();
-          if (content &&
-              content->IsElement() &&
-              content->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                nsGkAtoms::align,
-                                                NS_LITERAL_STRING("left"),
-                                                eIgnoreCase)) {
-            keepFloatOnSameLine = true;
-            // don't advance to next line (IE quirkie behaviour)
-            // it breaks rule CSS2/9.5.1/1, but what the hell
-            // since we cannot evangelize the world
-            break;
+          if (content) {
+            // we're interested only if previous frame is align=left
+            // IE messes things up when "right" (overlapping frames)
+            if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::align,
+                                     NS_LITERAL_STRING("left"), eIgnoreCase)) {
+              keepFloatOnSameLine = true;
+              // don't advance to next line (IE quirkie behaviour)
+              // it breaks rule CSS2/9.5.1/1, but what the hell
+              // since we cannot evangelize the world
+              break;
+            }
           }
         }
       }
 
       // the table does not fit anymore in this line so advance to next band
       mBCoord += floatAvailableSpace.mRect.BSize(wm);
       // To match nsBlockFrame::AdjustFloatAvailableSpace, we have to
       // get a new width for the new band.
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -1800,17 +1800,17 @@ nsContainerFrame::RenumberList()
   MOZ_ASSERT(mContent->IsHTMLElement(),
              "FrameStartsCounterScope should only return true for HTML elements");
 
   // Setup initial list ordinal value
   // XXX Map html's start property to counter-reset style
   int32_t ordinal = 1;
   int32_t increment;
   if (mContent->IsHTMLElement(nsGkAtoms::ol) &&
-      mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::reversed)) {
+      mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::reversed)) {
     increment = -1;
   } else {
     increment = 1;
   }
 
   nsGenericHTMLElement* hc = nsGenericHTMLElement::FromContent(mContent);
   // Must be non-null, since FrameStartsCounterScope only returns true
   // for HTML elements.
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -7764,17 +7764,17 @@ nsresult
 nsFrame::MakeFrameName(const nsAString& aType, nsAString& aResult) const
 {
   aResult = aType;
   if (mContent && !mContent->IsNodeOfType(nsINode::eTEXT)) {
     nsAutoString buf;
     mContent->NodeInfo()->NameAtom()->ToString(buf);
     if (IsSubDocumentFrame()) {
       nsAutoString src;
-      mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
+      mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
       buf.AppendLiteral(" src=");
       buf.Append(src);
     }
     aResult.Append('(');
     aResult.Append(buf);
     aResult.Append(')');
   }
   char buf[40];
@@ -9981,17 +9981,17 @@ nsIFrame::IsFocusable(int32_t *aTabIndex
         ui->mUserFocus != StyleUserFocus::None) {
       // Pass in default tabindex of -1 for nonfocusable and 0 for focusable
       tabIndex = 0;
     }
     isFocusable = mContent->IsFocusable(&tabIndex, aWithMouse);
     if (!isFocusable && !aWithMouse && IsScrollFrame() &&
         mContent->IsHTMLElement() &&
         !mContent->IsRootOfNativeAnonymousSubtree() && mContent->GetParent() &&
-        !mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
+        !mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
       // Elements with scrollable view are focusable with script & tabbable
       // Otherwise you couldn't scroll them with keyboard, which is
       // an accessibility issue (e.g. Section 508 rules)
       // However, we don't make them to be focusable with the mouse,
       // because the extra focus outlines are considered unnecessarily ugly.
       // When clicked on, the selection position within the element
       // will be enough to make them keyboard scrollable.
       nsIScrollableFrame *scrollFrame = do_QueryFrame(this);
@@ -10925,17 +10925,17 @@ nsIFrame::SetParent(nsContainerFrame* aP
 
 void
 nsIFrame::CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder,
                                  nsDisplayList* aList,
                                  bool* aCreatedContainerItem)
 {
   if (GetContent() &&
       GetContent()->IsXULElement() &&
-      GetContent()->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::layer)) {
+      GetContent()->HasAttr(kNameSpaceID_None, nsGkAtoms::layer)) {
     aList->AppendToTop(new (aBuilder)
         nsDisplayOwnLayer(aBuilder, this, aList, aBuilder->CurrentActiveScrolledRoot()));
     if (aCreatedContainerItem) {
       *aCreatedContainerItem = true;
     }
   }
 }
 
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -1123,19 +1123,17 @@ nsHTMLFramesetFrame::CanResize(bool aVer
   return true;
 }
 
 bool
 nsHTMLFramesetFrame::GetNoResize(nsIFrame* aChildFrame)
 {
   nsIContent* content = aChildFrame->GetContent();
 
-  return content &&
-    content->IsElement() &&
-    content->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::noresize);
+  return content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::noresize);
 }
 
 bool
 nsHTMLFramesetFrame::CanChildResize(bool aVertical, bool aLeft, int32_t aChildX)
 {
   nsIFrame* child = mFrames.FrameAt(aChildX);
   nsHTMLFramesetFrame* frameset = do_QueryFrame(child);
   return frameset ? frameset->CanResize(aVertical, aLeft) : !GetNoResize(child);
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -838,23 +838,23 @@ bool
 nsHTMLScrollFrame::IsXULCollapsed()
 {
   // We're never collapsed in the box sense.
   return false;
 }
 
 // Return the <browser> if the scrollframe is for the root frame directly
 // inside a <browser>.
-static Element*
+static nsIContent*
 GetBrowserRoot(nsIContent* aContent)
 {
   if (aContent) {
     nsIDocument* doc = aContent->GetUncomposedDoc();
     if (nsPIDOMWindowOuter* win = doc->GetWindow()) {
-      Element* frameElement = win->GetFrameElementInternal();
+      nsCOMPtr<Element> frameElement = win->GetFrameElementInternal();
       if (frameElement &&
           frameElement->NodeInfo()->Equals(nsGkAtoms::browser, kNameSpaceID_XUL))
         return frameElement;
     }
   }
 
   return nullptr;
 }
@@ -1028,17 +1028,17 @@ nsHTMLScrollFrame::Reflow(nsPresContext*
                          NEEDS_REFLOW(mHelper.mResizerBox);
 
     #undef NEEDS_REFLOW
   }
 
   if (mHelper.mIsRoot) {
     mHelper.mCollapsedResizer = true;
 
-    Element* browserRoot = GetBrowserRoot(mContent);
+    nsIContent* browserRoot = GetBrowserRoot(mContent);
     if (browserRoot) {
       bool showResizer = browserRoot->HasAttr(kNameSpaceID_None, nsGkAtoms::showresizer);
       reflowScrollCorner = showResizer == mHelper.mCollapsedResizer;
       mHelper.mCollapsedResizer = !showResizer;
     }
   }
 
   nsRect oldScrollAreaBounds = mHelper.mScrollPort;
@@ -3083,29 +3083,29 @@ AppendToTop(nsDisplayListBuilder* aBuild
     AppendInternalItemToTop(aLists, newItem, zIndex);
   } else {
     aLists.BorderBackground()->AppendToTop(newItem);
   }
 }
 
 struct HoveredStateComparator
 {
-  static bool Hovered(const nsIFrame* aFrame)
-  {
-      return aFrame->GetContent()->IsElement() &&
-             aFrame->GetContent()->AsElement()->HasAttr(kNameSpaceID_None,
-                                                        nsGkAtoms::hover);
-  }
-
   bool Equals(nsIFrame* A, nsIFrame* B) const {
-    return Hovered(A) == Hovered(B);
-  }
-
+    bool aHovered = A->GetContent()->HasAttr(kNameSpaceID_None,
+                                             nsGkAtoms::hover);
+    bool bHovered = B->GetContent()->HasAttr(kNameSpaceID_None,
+                                             nsGkAtoms::hover);
+    return aHovered == bHovered;
+  }
   bool LessThan(nsIFrame* A, nsIFrame* B) const {
-    return !Hovered(A) && Hovered(B);
+    bool aHovered = A->GetContent()->HasAttr(kNameSpaceID_None,
+                                             nsGkAtoms::hover);
+    bool bHovered = B->GetContent()->HasAttr(kNameSpaceID_None,
+                                             nsGkAtoms::hover);
+    return !aHovered && bHovered;
   }
 };
 
 void
 ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder*   aBuilder,
                                        const nsDisplayListSet& aLists,
                                        bool                    aCreateLayer,
                                        bool                    aPositioned)
@@ -4505,20 +4505,17 @@ ScrollFrameHelper::ReloadChildFrames()
 
   for (nsIFrame* frame : mOuter->PrincipalChildList()) {
     nsIContent* content = frame->GetContent();
     if (content == mOuter->GetContent()) {
       NS_ASSERTION(!mScrolledFrame, "Already found the scrolled frame");
       mScrolledFrame = frame;
     } else {
       nsAutoString value;
-      if (content->IsElement()) {
-        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::orient,
-                                      value);
-      }
+      content->GetAttr(kNameSpaceID_None, nsGkAtoms::orient, value);
       if (!value.IsEmpty()) {
         // probably a scrollbar then
         if (value.LowerCaseEqualsLiteral("horizontal")) {
           NS_ASSERTION(!mHScrollbarBox, "Found multiple horizontal scrollbars?");
           mHScrollbarBox = frame;
         } else {
           NS_ASSERTION(!mVScrollbarBox, "Found multiple vertical scrollbars?");
           mVScrollbarBox = frame;
@@ -4679,17 +4676,17 @@ ScrollFrameHelper::CreateAnonymousConten
         dir.AssignLiteral("bottomend");
         break;
       default:
         NS_WARNING("only resizable types should have resizers");
     }
     mResizerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, dir, false);
 
     if (mIsRoot) {
-      Element* browserRoot = GetBrowserRoot(mOuter->GetContent());
+      nsIContent* browserRoot = GetBrowserRoot(mOuter->GetContent());
       mCollapsedResizer = !(browserRoot &&
                             browserRoot->HasAttr(kNameSpaceID_None, nsGkAtoms::showresizer));
     }
     else {
       mResizerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::element,
                                     NS_LITERAL_STRING("_parent"), false);
     }
 
@@ -4797,24 +4794,22 @@ ScrollFrameHelper::UpdateScrollbarPositi
     if (!weakFrame.IsAlive()) {
       return;
     }
   }
 
   mFrameIsUpdatingScrollbar = false;
 }
 
-void ScrollFrameHelper::CurPosAttributeChanged(nsIContent* aContent,
-                                               bool aDoScroll)
+void ScrollFrameHelper::CurPosAttributeChanged(nsIContent* aContent, bool aDoScroll)
 {
   NS_ASSERTION(aContent, "aContent must not be null");
   NS_ASSERTION((mHScrollbarBox && mHScrollbarBox->GetContent() == aContent) ||
                (mVScrollbarBox && mVScrollbarBox->GetContent() == aContent),
                "unexpected child");
-  MOZ_ASSERT(aContent->IsElement());
 
   // Attribute changes on the scrollbars happen in one of three ways:
   // 1) The scrollbar changed the attribute in response to some user event
   // 2) We changed the attribute in response to a ScrollPositionDidChange
   // callback from the scrolling view
   // 3) We changed the attribute to adjust the scrollbars for the start
   // of a smooth scroll operation
   //
@@ -4843,18 +4838,17 @@ void ScrollFrameHelper::CurPosAttributeC
     return;
   }
 
   if (mScrollbarActivity) {
     RefPtr<ScrollbarActivity> scrollbarActivity(mScrollbarActivity);
     scrollbarActivity->ActivityOccurred();
   }
 
-  const bool isSmooth =
-    aContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::smooth);
+  bool isSmooth = aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::smooth);
   if (isSmooth) {
     // Make sure an attribute-setting callback occurs even if the view
     // didn't actually move yet.  We need to make sure other listeners
     // see that the scroll position is not (yet) what they thought it
     // was.
     AutoWeakFrame weakFrame(mOuter);
     UpdateScrollbarPosition();
     if (!weakFrame.IsAlive()) {
@@ -5591,18 +5585,18 @@ ScrollFrameHelper::ReflowFinished()
   // scrolling.  So we suppress the effect of the changes above with
   // mFrameIsUpdatingScrollbar and call CurPosAttributeChanged here.
   // (It actually even works some of the time without this, thanks to
   // nsSliderFrame::AttributeChanged's handling of maxpos, but not when
   // we hide the scrollbar on a large size change, such as
   // maximization.)
   if (!mHScrollbarBox && !mVScrollbarBox)
     return false;
-  CurPosAttributeChanged(mVScrollbarBox ? mVScrollbarBox->GetContent()->AsElement()
-                                        : mHScrollbarBox->GetContent()->AsElement(),
+  CurPosAttributeChanged(mVScrollbarBox ? mVScrollbarBox->GetContent()
+                                        : mHScrollbarBox->GetContent(),
                          doScroll);
   return doScroll;
 }
 
 void
 ScrollFrameHelper::ReflowCallbackCanceled()
 {
   mPostedReflowCallback = false;
@@ -6136,19 +6130,17 @@ ScrollFrameHelper::GetCoordAttribute(nsI
                                          nscoord aDefaultValue,
                                          nscoord* aRangeStart,
                                          nscoord* aRangeLength)
 {
   if (aBox) {
     nsIContent* content = aBox->GetContent();
 
     nsAutoString value;
-    if (content->IsElement()) {
-      content->AsElement()->GetAttr(kNameSpaceID_None, aAtom, value);
-    }
+    content->GetAttr(kNameSpaceID_None, aAtom, value);
     if (!value.IsEmpty()) {
       nsresult error;
       // convert it to appunits
       nscoord result = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
       nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f);
       // Any nscoord value that would round to the attribute value when converted
       // to CSS pixels is allowed.
       *aRangeStart = result - halfPixel;
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -916,19 +916,17 @@ nsImageFrame::GetInnerArea() const
 {
   return GetContentRectRelativeToSelf();
 }
 
 Element*
 nsImageFrame::GetMapElement() const
 {
   nsAutoString usemap;
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                     nsGkAtoms::usemap,
-                                     usemap)) {
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, usemap)) {
     return mContent->OwnerDoc()->FindImageMap(usemap);
   }
   return nullptr;
 }
 
 // get the offset into the content area of the image where aImg starts if it is a continuation.
 nscoord
 nsImageFrame::GetContinuationOffset() const
@@ -1498,17 +1496,17 @@ nsImageFrame::DisplayAltFeedback(gfxCont
     }
   }
 
   // If there's still room, display the alt-text
   if (!inner.IsEmpty()) {
     nsIContent* content = GetContent();
     if (content) {
       nsAutoString altText;
-      nsCSSFrameConstructor::GetAlternateTextFor(content->AsElement(),
+      nsCSSFrameConstructor::GetAlternateTextFor(content,
                                                  content->NodeInfo()->NameAtom(),
                                                  altText);
       DisplayAltText(PresContext(), aRenderingContext, altText, inner);
     }
   }
 
   aRenderingContext.Restore();
 
@@ -1964,17 +1962,17 @@ nsImageFrame::GetImageMap()
   }
 
   return mImageMap;
 }
 
 bool
 nsImageFrame::IsServerImageMap()
 {
-  return mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::ismap);
+  return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::ismap);
 }
 
 // Translate an point that is relative to our frame
 // into a localized pixel coordinate that is relative to the
 // content area of this frame (inside the border+padding).
 void
 nsImageFrame::TranslateEventCoords(const nsPoint& aPoint,
                                    nsIntPoint&     aResult)
--- a/layout/generic/nsImageMap.cpp
+++ b/layout/generic/nsImageMap.cpp
@@ -786,28 +786,28 @@ nsImageMap::UpdateAreas()
     accService->UpdateImageMap(mImageFrame);
   }
 #endif
 }
 
 void
 nsImageMap::AddArea(HTMLAreaElement* aArea)
 {
-  static Element::AttrValuesArray strings[] =
+  static nsIContent::AttrValuesArray strings[] =
     {&nsGkAtoms::rect, &nsGkAtoms::rectangle,
      &nsGkAtoms::circle, &nsGkAtoms::circ,
      &nsGkAtoms::_default,
      &nsGkAtoms::poly, &nsGkAtoms::polygon,
      nullptr};
 
   UniquePtr<Area> area;
   switch (aArea->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::shape,
                                  strings, eIgnoreCase)) {
-  case Element::ATTR_VALUE_NO_MATCH:
-  case Element::ATTR_MISSING:
+  case nsIContent::ATTR_VALUE_NO_MATCH:
+  case nsIContent::ATTR_MISSING:
   case 0:
   case 1:
     area = MakeUnique<RectArea>(aArea);
     break;
   case 2:
   case 3:
     area = MakeUnique<CircleArea>(aArea);
     break;
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -766,19 +766,17 @@ nsPluginFrame::IsHidden(bool aCheckVisib
     // Yes, these are really the kooky ways that you could tell 4.x
     // not to hide the <embed> once you'd put the 'hidden' attribute
     // on the tag...
 
     // HIDDEN w/ no attributes gets translated as we are hidden for
     // compatibility w/ 4.x and IE so we don't create a non-painting
     // widget in layout. See bug 188959.
     nsAutoString hidden;
-    if (mContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                       nsGkAtoms::hidden,
-                                       hidden) &&
+    if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::hidden, hidden) &&
        (hidden.IsEmpty() ||
         (!hidden.LowerCaseEqualsLiteral("false") &&
          !hidden.LowerCaseEqualsLiteral("no") &&
          !hidden.LowerCaseEqualsLiteral("off")))) {
       return true;
     }
   }
 
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -2144,27 +2144,27 @@ BuildTextRunsScanner::BuildTextRunForFra
     } else if (mLineContainer->GetStateBits() & NS_FRAME_IS_IN_SINGLE_CHAR_MI) {
       flags2 |= nsTextFrameUtils::Flags::TEXT_IS_SINGLE_CHAR_MI;
       anyMathMLStyling = true;
       // Test for fontstyle attribute as StyleFont() may not be accurate
       // To be consistent in terms of ignoring CSS style changes, fontweight
       // gets checked too.
       if (parent) {
         nsIContent* content = parent->GetContent();
-        if (content && content->IsElement()) {
-          if (content->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                nsGkAtoms::fontstyle_,
-                                                NS_LITERAL_STRING("normal"),
-                                                eCaseMatters)) {
+        if (content) {
+          if (content->AttrValueIs(kNameSpaceID_None,
+                                  nsGkAtoms::fontstyle_,
+                                  NS_LITERAL_STRING("normal"),
+                                  eCaseMatters)) {
             mathFlags |= MathMLTextRunFactory::MATH_FONT_STYLING_NORMAL;
           }
-          if (content->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                                nsGkAtoms::fontweight_,
-                                                NS_LITERAL_STRING("bold"),
-                                                eCaseMatters)) {
+          if (content->AttrValueIs(kNameSpaceID_None,
+                                   nsGkAtoms::fontweight_,
+                                   NS_LITERAL_STRING("bold"),
+                                   eCaseMatters)) {
             mathFlags |= MathMLTextRunFactory::MATH_FONT_WEIGHT_BOLD;
           }
         }
       }
     }
     if (mLineContainer->HasAnyStateBits(TEXT_IS_IN_TOKEN_MATHML)) {
       // All MathML tokens except <mtext> use 'math' script.
       if (!(parent && parent->GetContent() &&
--- a/layout/mathml/nsMathMLmactionFrame.cpp
+++ b/layout/mathml/nsMathMLmactionFrame.cpp
@@ -38,20 +38,17 @@ enum nsMactionActionTypes {
 
 // helper function to parse actiontype attribute
 static int32_t
 GetActionType(nsIContent* aContent)
 {
   nsAutoString value;
 
   if (aContent) {
-    if (!aContent->IsElement() ||
-        !aContent->AsElement()->GetAttr(kNameSpaceID_None,
-                                        nsGkAtoms::actiontype_,
-                                        value))
+    if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::actiontype_, value))
       return NS_MATHML_ACTION_TYPE_NONE;
   }
 
   if (value.EqualsLiteral("toggle"))
     return NS_MATHML_ACTION_TYPE_TOGGLE;
   if (value.EqualsLiteral("statusline"))
     return NS_MATHML_ACTION_TYPE_STATUSLINE;
   if (value.EqualsLiteral("tooltip"))
@@ -129,17 +126,17 @@ nsMathMLmactionFrame::GetSelectedFrame()
     // and it's inefficient to count the children. It's fine to leave
     // it be equal -1 because it's not used with other actiontypes.
     mSelection = 1;
     mInvalidMarkup = false;
     mSelectedFrame = mFrames.FirstChild();
     return mSelectedFrame;
   }
 
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::selection_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::selection_, value);
   if (!value.IsEmpty()) {
     nsresult errorCode;
     selection = value.ToInteger(&errorCode);
     if (NS_FAILED(errorCode))
       selection = 1;
   }
   else selection = 1; // default is first frame
 
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -153,17 +153,17 @@ void nsMathMLmencloseFrame::InitNotation
 {
   MarkNeedsDisplayItemRebuild();
   mNotationsToDraw.clear();
   mLongDivCharIndex = mRadicalCharIndex = -1;
   mMathMLChar.Clear();
 
   nsAutoString value;
 
-  if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::notation_, value)) {
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::notation_, value)) {
     // parse the notation attribute
     nsWhitespaceTokenizer tokenizer(value);
 
     while (tokenizer.hasMoreTokens())
       AddNotation(tokenizer.nextToken());
 
     if (IsToDraw(NOTATION_UPDIAGONALARROW)) {
       // For <menclose notation="updiagonalstrike updiagonalarrow">, if
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -96,45 +96,45 @@ nsMathMLmfencedFrame::RemoveFencesAndSep
 
 void
 nsMathMLmfencedFrame::CreateFencesAndSeparators(nsPresContext* aPresContext)
 {
   nsAutoString value;
 
   //////////////
   // see if the opening fence is there ...
-  if (!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::open, value)) {
+  if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::open, value)) {
     value = char16_t('('); // default as per the MathML REC
   } else {
     value.CompressWhitespace();
   }
 
   if (!value.IsEmpty()) {
     mOpenChar = new nsMathMLChar;
     mOpenChar->SetData(value);
     ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mOpenChar);
   }
 
   //////////////
   // see if the closing fence is there ...
-  if(!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::close, value)) {
+  if(!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::close, value)) {
     value = char16_t(')'); // default as per the MathML REC
   } else {
     value.CompressWhitespace();
   }
 
   if (!value.IsEmpty()) {
     mCloseChar = new nsMathMLChar;
     mCloseChar->SetData(value);
     ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mCloseChar);
   }
 
   //////////////
   // see if separators are there ...
-  if (!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::separators_, value)) {
+  if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::separators_, value)) {
     value = char16_t(','); // default as per the MathML REC
   } else {
     value.StripWhitespace();
   }
 
   mSeparatorsCount = value.Length();
   if (0 < mSeparatorsCount) {
     int32_t sepCount = mFrames.GetLength() - 1;
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -250,23 +250,23 @@ nsMathMLmfracFrame::PlaceInternal(DrawTa
   if (mEmbellishData.coreFrame) {
     nsEmbellishData parentData;
     GetEmbellishDataFrom(GetParent(), parentData);
     outermostEmbellished = parentData.coreFrame != mEmbellishData.coreFrame;
   }
 
   // see if the linethickness attribute is there
   nsAutoString value;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::linethickness_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::linethickness_, value);
   mLineThickness = CalcLineThickness(presContext, mStyleContext, value,
                                      onePixel, defaultRuleThickness,
                                      fontSizeInflation);
 
   // bevelled attribute
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::bevelled_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::bevelled_, value);
   mIsBevelled = value.EqualsLiteral("true");
 
   bool displayStyle = StyleFont()->mMathDisplay == NS_MATHML_DISPLAYSTYLE_BLOCK;
 
   if (!mIsBevelled) {
     mLineRect.height = mLineThickness;
 
     // by default, leave at least one-pixel padding at either end, and add
@@ -408,24 +408,24 @@ nsMathMLmfracFrame::PlaceInternal(DrawTa
     // XXX Need revisiting the width. TeX uses the exact width
     // e.g. in $$\huge\frac{\displaystyle\int}{i}$$
     nscoord width = std::max(bmNum.width, bmDen.width);
     nscoord dxNum = leftSpace + (width - sizeNum.Width())/2;
     nscoord dxDen = leftSpace + (width - sizeDen.Width())/2;
     width += leftSpace + rightSpace;
 
     // see if the numalign attribute is there
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::numalign_, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::numalign_, value);
     if (value.EqualsLiteral("left"))
       dxNum = leftSpace;
     else if (value.EqualsLiteral("right"))
       dxNum = width - rightSpace - sizeNum.Width();
 
     // see if the denomalign attribute is there
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::denomalign_, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::denomalign_, value);
     if (value.EqualsLiteral("left"))
       dxDen = leftSpace;
     else if (value.EqualsLiteral("right"))
       dxDen = width - rightSpace - sizeDen.Width();
 
     mBoundingMetrics.rightBearing =
       std::max(dxNum + bmNum.rightBearing, dxDen + bmDen.rightBearing);
     if (mBoundingMetrics.rightBearing < width - rightSpace)
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
@@ -108,17 +108,17 @@ nsMathMLmmultiscriptsFrame::Place(DrawTa
   // values: length
   // default: automatic
   //
   // We use 0 as the default value so unitless values can be ignored.
   // As a minimum, negative values can be ignored.
   //
   nsAutoString value;
   if (!mContent->IsMathMLElement(nsGkAtoms::msup_)) {
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::subscriptshift_, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::subscriptshift_, value);
     if (!value.IsEmpty()) {
       ParseNumericValue(value, &subScriptShift, 0, PresContext(),
                         mStyleContext, fontSizeInflation);
     }
   }
   // superscriptshift
   //
   // "Specifies the minimum amount to shift the baseline of superscript up; the
@@ -126,17 +126,17 @@ nsMathMLmmultiscriptsFrame::Place(DrawTa
   //
   // values: length
   // default: automatic
   //
   // We use 0 as the default value so unitless values can be ignored.
   // As a minimum, negative values can be ignored.
   //
   if (!mContent->IsMathMLElement(nsGkAtoms::msub_)) {
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::superscriptshift_, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::superscriptshift_, value);
     if (!value.IsEmpty()) {
       ParseNumericValue(value, &supScriptShift, 0, PresContext(),
                         mStyleContext, fontSizeInflation);
     }
   }
   return PlaceMultiScript(PresContext(), aDrawTarget, aPlaceOrigin,
                           aDesiredSize, this, subScriptShift, supScriptShift,
                           fontSizeInflation);
--- a/layout/mathml/nsMathMLmoFrame.cpp
+++ b/layout/mathml/nsMathMLmoFrame.cpp
@@ -244,24 +244,24 @@ nsMathMLmoFrame::ProcessOperatorData()
     // default values from the Operator Dictionary were obtained in ProcessTextData()
     // and these special bits are always kept in mFlags
     if (NS_MATHML_OPERATOR_IS_ACCENT(mFlags))
       mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT;
     if (NS_MATHML_OPERATOR_IS_MOVABLELIMITS(mFlags))
       mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS;
 
     // see if the accent attribute is there
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::accent_, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accent_, value);
     if (value.EqualsLiteral("true"))
       mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT;
     else if (value.EqualsLiteral("false"))
       mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT;
 
     // see if the movablelimits attribute is there
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::movablelimits_, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::movablelimits_, value);
     if (value.EqualsLiteral("true"))
       mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS;
     else if (value.EqualsLiteral("false"))
       mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_MOVABLELIMITS;
 
      // ---------------------------------------------------------------------
      // we will be called again to re-sync the rest of our state next time...
      // (nobody needs the other values below at this stage)
@@ -316,17 +316,17 @@ nsMathMLmoFrame::ProcessOperatorData()
     if (zeroSpacing) {
       mFlags |= NS_MATHML_OPERATOR_EMBELLISH_ISOLATED;
     } else {
       mFlags &= ~NS_MATHML_OPERATOR_EMBELLISH_ISOLATED;
     }
 
     // find our form
     form = NS_MATHML_OPERATOR_FORM_INFIX;
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::form, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::form, value);
     if (!value.IsEmpty()) {
       if (value.EqualsLiteral("prefix"))
         form = NS_MATHML_OPERATOR_FORM_PREFIX;
       else if (value.EqualsLiteral("postfix"))
         form = NS_MATHML_OPERATOR_FORM_POSTFIX;
     }
     else {
       // set our form flag depending on the position
@@ -383,17 +383,17 @@ nsMathMLmoFrame::ProcessOperatorData()
   // default: set by dictionary (thickmathspace)
   //
   // XXXfredw Support for negative and relative values is not implemented
   // (bug 805926).
   // Relative values will give a multiple of the current leading space,
   // which is not necessarily the default one.
   //
   nscoord leadingSpace = mEmbellishData.leadingSpace;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::lspace_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::lspace_, value);
   if (!value.IsEmpty()) {
     nsCSSValue cssValue;
     if (nsMathMLElement::ParseNumericValue(value, cssValue, 0,
                                            mContent->OwnerDoc())) {
       if ((eCSSUnit_Number == cssValue.GetUnit()) && !cssValue.GetFloatValue())
         leadingSpace = 0;
       else if (cssValue.IsLengthUnit())
         leadingSpace = CalcLength(presContext, mStyleContext, cssValue,
@@ -410,17 +410,17 @@ nsMathMLmoFrame::ProcessOperatorData()
   // default: set by dictionary (thickmathspace)
   //
   // XXXfredw Support for negative and relative values is not implemented
   // (bug 805926).
   // Relative values will give a multiple of the current leading space,
   // which is not necessarily the default one.
   //
   nscoord trailingSpace = mEmbellishData.trailingSpace;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::rspace_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rspace_, value);
   if (!value.IsEmpty()) {
     nsCSSValue cssValue;
     if (nsMathMLElement::ParseNumericValue(value, cssValue, 0,
                                            mContent->OwnerDoc())) {
       if ((eCSSUnit_Number == cssValue.GetUnit()) && !cssValue.GetFloatValue())
         trailingSpace = 0;
       else if (cssValue.IsLengthUnit())
         trailingSpace = CalcLength(presContext, mStyleContext, cssValue,
@@ -448,43 +448,43 @@ nsMathMLmoFrame::ProcessOperatorData()
   // dictionary can cause conflicts in the rest of the stretching algorithms
   // (e.g. all largeops are assumed to have a vertical direction)
 
   // For each attribute overriden by the user, turn off its bit flag.
   // symmetric|movablelimits|separator|largeop|accent|fence|stretchy|form
   // special: accent and movablelimits are handled above,
   // don't process them here
 
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::stretchy_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::stretchy_, value);
   if (value.EqualsLiteral("false")) {
     mFlags &= ~NS_MATHML_OPERATOR_STRETCHY;
   } else if (value.EqualsLiteral("true")) {
     mFlags |= NS_MATHML_OPERATOR_STRETCHY;
   }
   if (NS_MATHML_OPERATOR_IS_FENCE(mFlags)) {
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::fence_, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::fence_, value);
     if (value.EqualsLiteral("false"))
       mFlags &= ~NS_MATHML_OPERATOR_FENCE;
     else
       mEmbellishData.flags |= NS_MATHML_EMBELLISH_FENCE;
   }
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::largeop_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::largeop_, value);
   if (value.EqualsLiteral("false")) {
     mFlags &= ~NS_MATHML_OPERATOR_LARGEOP;
   } else if (value.EqualsLiteral("true")) {
     mFlags |= NS_MATHML_OPERATOR_LARGEOP;
   }
   if (NS_MATHML_OPERATOR_IS_SEPARATOR(mFlags)) {
-    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::separator_, value);
+    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::separator_, value);
     if (value.EqualsLiteral("false"))
       mFlags &= ~NS_MATHML_OPERATOR_SEPARATOR;
     else
       mEmbellishData.flags |= NS_MATHML_EMBELLISH_SEPARATOR;
   }
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::symmetric_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::symmetric_, value);
   if (value.EqualsLiteral("false"))
     mFlags &= ~NS_MATHML_OPERATOR_SYMMETRIC;
   else if (value.EqualsLiteral("true"))
     mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
 
 
   // minsize
   //
@@ -494,17 +494,17 @@ nsMathMLmoFrame::ProcessOperatorData()
   // default: set by dictionary (1em)
   //
   // We don't allow negative values.
   // Note: Contrary to other "length" values, unitless and percentage do not
   // give a multiple of the defaut value but a multiple of the operator at
   // normal size.
   //
   mMinSize = 0;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::minsize_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::minsize_, value);
   if (!value.IsEmpty()) {
     nsCSSValue cssValue;
     if (nsMathMLElement::ParseNumericValue(value, cssValue,
                                            nsMathMLElement::
                                            PARSE_ALLOW_UNITLESS,
                                            mContent->OwnerDoc())) {
       nsCSSUnit unit = cssValue.GetUnit();
       if (eCSSUnit_Number == unit)
@@ -527,17 +527,17 @@ nsMathMLmoFrame::ProcessOperatorData()
   // default: set by dictionary (infinity)
   //
   // We don't allow negative values.
   // Note: Contrary to other "length" values, unitless and percentage do not
   // give a multiple of the defaut value but a multiple of the operator at
   // normal size.
   //
   mMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::maxsize_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::maxsize_, value);
   if (!value.IsEmpty()) {
     nsCSSValue cssValue;
     if (nsMathMLElement::ParseNumericValue(value, cssValue,
                                            nsMathMLElement::
                                            PARSE_ALLOW_UNITLESS,
                                            mContent->OwnerDoc())) {
       nsCSSUnit unit = cssValue.GetUnit();
       if (eCSSUnit_Number == unit)
--- a/layout/mathml/nsMathMLmpaddedFrame.cpp
+++ b/layout/mathml/nsMathMLmpaddedFrame.cpp
@@ -61,54 +61,54 @@ nsMathMLmpaddedFrame::ProcessAttributes(
   lspace = [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | h-unit | namedspace)
   voffset= [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | v-unit | namedspace)
   */
 
   nsAutoString value;
 
   // width
   mWidthSign = NS_MATHML_SIGN_INVALID;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
   if (!value.IsEmpty()) {
     if (!ParseAttribute(value, mWidthSign, mWidth, mWidthPseudoUnit)) {
       ReportParseError(nsGkAtoms::width->GetUTF16String(), value.get());
     }
   }
 
   // height
   mHeightSign = NS_MATHML_SIGN_INVALID;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::height, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::height, value);
   if (!value.IsEmpty()) {
     if (!ParseAttribute(value, mHeightSign, mHeight, mHeightPseudoUnit)) {
       ReportParseError(nsGkAtoms::height->GetUTF16String(), value.get());
     }
   }
 
   // depth
   mDepthSign = NS_MATHML_SIGN_INVALID;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::depth_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::depth_, value);
   if (!value.IsEmpty()) {
     if (!ParseAttribute(value, mDepthSign, mDepth, mDepthPseudoUnit)) {
       ReportParseError(nsGkAtoms::depth_->GetUTF16String(), value.get());
     }
   }
 
   // lspace
   mLeadingSpaceSign = NS_MATHML_SIGN_INVALID;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::lspace_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::lspace_, value);
   if (!value.IsEmpty()) {
     if (!ParseAttribute(value, mLeadingSpaceSign, mLeadingSpace,
                         mLeadingSpacePseudoUnit)) {
       ReportParseError(nsGkAtoms::lspace_->GetUTF16String(), value.get());
     }
   }
 
   // voffset
   mVerticalOffsetSign = NS_MATHML_SIGN_INVALID;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::voffset_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::voffset_, value);
   if (!value.IsEmpty()) {
     if (!ParseAttribute(value, mVerticalOffsetSign, mVerticalOffset,
                         mVerticalOffsetPseudoUnit)) {
       ReportParseError(nsGkAtoms::voffset_->GetUTF16String(), value.get());
     }
   }
 
 }
--- a/layout/mathml/nsMathMLmspaceFrame.cpp
+++ b/layout/mathml/nsMathMLmspaceFrame.cpp
@@ -40,17 +40,17 @@ nsMathMLmspaceFrame::ProcessAttributes(n
   // default: 0em
   //
   // The default value is "0em", so unitless values can be ignored.
   // <mspace/> is listed among MathML elements allowing negative spacing and
   // the MathML test suite contains "Presentation/TokenElements/mspace/mspace2"
   // as an example. Hence we allow negative values.
   //
   mWidth = 0;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
   if (!value.IsEmpty()) {
     ParseNumericValue(value, &mWidth,
                       nsMathMLElement::PARSE_ALLOW_NEGATIVE,
                       aPresContext, mStyleContext, fontSizeInflation);
   }
 
   // height
   //
@@ -58,34 +58,34 @@ nsMathMLmspaceFrame::ProcessAttributes(n
   //
   // values: length
   // default: 0ex
   //
   // The default value is "0ex", so unitless values can be ignored.
   // We do not allow negative values. See bug 716349.
   //
   mHeight = 0;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::height, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::height, value);
   if (!value.IsEmpty()) {
     ParseNumericValue(value, &mHeight, 0,
                       aPresContext, mStyleContext, fontSizeInflation);
   }
 
   // depth
   //
   // "Specifies the desired depth (below the baseline) of the space."
   //
   // values: length
   // default: 0ex
   //
   // The default value is "0ex", so unitless values can be ignored.
   // We do not allow negative values. See bug 716349.
   //
   mDepth = 0;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::depth_, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::depth_, value);
   if (!value.IsEmpty()) {
     ParseNumericValue(value, &mDepth, 0,
                       aPresContext, mStyleContext, fontSizeInflation);
   }
 }
 
 void
 nsMathMLmspaceFrame::Reflow(nsPresContext*          aPresContext,
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -352,18 +352,18 @@ public:
 
 static void
 ParseFrameAttribute(nsIFrame* aFrame,
                     nsAtom* aAttribute,
                     bool aAllowMultiValues)
 {
   nsAutoString attrValue;
 
-  Element* frameElement = aFrame->GetContent()->AsElement();
-  frameElement->GetAttr(kNameSpaceID_None, aAttribute, attrValue);
+  nsIContent* frameContent = aFrame->GetContent();
+  frameContent->GetAttr(kNameSpaceID_None, aAttribute, attrValue);
 
   if (!attrValue.IsEmpty()) {
     nsTArray<int8_t>* valueList =
       ExtractStyleValues(attrValue, aAttribute, aAllowMultiValues);
 
     // If valueList is null, that indicates a problem with the attribute value.
     // Only set properties on a valid attribute value.
     if (valueList) {
@@ -499,22 +499,22 @@ static void
 ParseSpacingAttribute(nsMathMLmtableFrame* aFrame, nsAtom* aAttribute)
 {
   NS_ASSERTION(aAttribute == nsGkAtoms::rowspacing_ ||
                aAttribute == nsGkAtoms::columnspacing_ ||
                aAttribute == nsGkAtoms::framespacing_,
                "Non spacing attribute passed");
 
   nsAutoString attrValue;
-  Element* frameElement = aFrame->GetContent()->AsElement();
-  frameElement->GetAttr(kNameSpaceID_None, aAttribute, attrValue);
+  nsIContent* frameContent = aFrame->GetContent();
+  frameContent->GetAttr(kNameSpaceID_None, aAttribute, attrValue);
 
   if (nsGkAtoms::framespacing_ == aAttribute) {
     nsAutoString frame;
-    frameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::frame, frame);
+    frameContent->GetAttr(kNameSpaceID_None, nsGkAtoms::frame, frame);
     if (frame.IsEmpty() || frame.EqualsLiteral("none")) {
       aFrame->SetFrameSpacing(0, 0);
       return;
     }
   }
 
   nscoord value;
   nscoord value2;
@@ -532,25 +532,25 @@ ParseSpacingAttribute(nsMathMLmtableFram
     value = kDefaultFramespacingArg0Em * fm->EmHeight();
     value2 = kDefaultFramespacingArg1Ex * fm->XHeight();
   }
 
   nsTArray<nscoord> valueList;
   ExtractSpacingValues(attrValue, aAttribute, valueList, aFrame, value, value2,
                        fontSizeInflation);
   if (valueList.Length() == 0) {
-    if (frameElement->HasAttr(kNameSpaceID_None, aAttribute)) {
+    if (frameContent->HasAttr(kNameSpaceID_None, aAttribute)) {
       ReportParseError(aFrame, aAttribute->GetUTF16String(),
                        attrValue.get());
     }
     valueList.AppendElement(value);
   }
   if (aAttribute == nsGkAtoms::framespacing_) {
     if (valueList.Length() == 1) {
-      if(frameElement->HasAttr(kNameSpaceID_None, aAttribute)) {
+      if(frameContent->HasAttr(kNameSpaceID_None, aAttribute)) {
         ReportParseError(aFrame, aAttribute->GetUTF16String(),
                          attrValue.get());
       }
       valueList.AppendElement(value2);
     } else if (valueList.Length() != 2) {
       ReportParseError(aFrame, aAttribute->GetUTF16String(),
                        attrValue.get());
     }
@@ -839,17 +839,17 @@ nsMathMLmtableWrapperFrame::Reflow(nsPre
 
   nsTableWrapperFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
   NS_ASSERTION(aDesiredSize.Height() >= 0, "illegal height for mtable");
   NS_ASSERTION(aDesiredSize.Width() >= 0, "illegal width for mtable");
 
   // see if the user has set the align attribute on the <mtable>
   int32_t rowIndex = 0;
   eAlign tableAlign = eAlign_axis;
-  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::align, value);
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::align, value);
   if (!value.IsEmpty()) {
     ParseAlignAttribute(value, tableAlign, rowIndex);
   }
 
   // adjustments if there is a specified row from where to anchor the table
   // (conceptually: when there is no row of reference, picture the table as if
   // it is wrapped in a single big fictional row at dy = 0, this way of
   // doing so allows us to have a single code path for all cases).
@@ -1083,19 +1