Bug 1173199 - Create preference to disable MathML. r=huseby, r=smaug
☠☠ backed out by 03c7ee730909 ☠ ☠
authorJonathan Kingston <jkt@mozilla.com>
Tue, 28 Jun 2016 15:24:48 +0100
changeset 347186 c0bf6e0b8f1d0a2819a55bc737bb1596adf2874e
parent 347185 d300e4be79b79acb1a70c0e0b1128ac5ed58a59e
child 347187 96527a436bd86b0d83bb4f73b17c21b847ed40d7
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershuseby, smaug
bugs1173199
milestone50.0a1
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
Bug 1173199 - Create preference to disable MathML. r=huseby, r=smaug If the mathml.disabled preference is true, treat <math> and other MathML elements as generic XML elements. This patch disables the rendering code of MathML however preserves the namespace so to reduce the breakage. Original patch by: Kathy Brade <brade@pearlcrescent.com> MozReview-Commit-ID: A2f2Q2b4eqR
dom/base/Element.cpp
dom/base/NameSpaceConstants.h
dom/base/NodeInfo.cpp
dom/base/nsContentUtils.cpp
dom/base/nsDOMAttributeMap.cpp
dom/base/nsNameSpaceManager.cpp
dom/base/nsNameSpaceManager.h
dom/svg/SVGAnimationElement.cpp
dom/svg/SVGAnimationElement.h
dom/svg/SVGGraphicsElement.cpp
dom/svg/SVGGraphicsElement.h
dom/svg/SVGSymbolElement.cpp
dom/svg/SVGSymbolElement.h
dom/svg/SVGTests.cpp
dom/svg/SVGTests.h
dom/svg/nsSVGFeatures.cpp
dom/svg/nsSVGFeatures.h
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xml/nsXMLContentSink.cpp
layout/mathml/moz.build
layout/mathml/tests/chrome.ini
layout/mathml/tests/mathml_example_test.html
layout/mathml/tests/mochitest.ini
layout/mathml/tests/test_disabled.html
layout/mathml/tests/test_disabled_chrome.html
layout/reftests/mathml/disabled-scriptlevel-1-ref.html
layout/reftests/mathml/disabled-scriptlevel-1-ref.xhtml
layout/reftests/mathml/disabled-scriptlevel-1.html
layout/reftests/mathml/disabled-scriptlevel-1.xhtml
layout/reftests/mathml/reftest.list
layout/style/ServoBindings.cpp
modules/libpref/init/all.js
testing/web-platform/mozilla/meta/MANIFEST.json
testing/web-platform/mozilla/meta/html/syntax/parsing/math-parse01.html.ini
testing/web-platform/mozilla/tests/html/syntax/parsing/math-parse01.html
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1253,17 +1253,17 @@ Element::RemoveAttributeNode(Attr& aAttr
 }
 
 void
 Element::GetAttributeNS(const nsAString& aNamespaceURI,
                         const nsAString& aLocalName,
                         nsAString& aReturn)
 {
   int32_t nsid =
-    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
+    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI, OwnerDoc());
 
   if (nsid == kNameSpaceID_Unknown) {
     // Unknown namespace means no attribute.
     SetDOMStringToNull(aReturn);
     return;
   }
 
   nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
@@ -1295,17 +1295,17 @@ Element::SetAttributeNS(const nsAString&
 
 void
 Element::RemoveAttributeNS(const nsAString& aNamespaceURI,
                            const nsAString& aLocalName,
                            ErrorResult& aError)
 {
   nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
   int32_t nsid =
-    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
+    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI, OwnerDoc());
 
   if (nsid == kNameSpaceID_Unknown) {
     // If the namespace ID is unknown, it means there can't possibly be an
     // existing attribute. We would need a known namespace ID to pass into
     // UnsetAttr, so we return early if we don't have one.
     return;
   }
 
@@ -1372,17 +1372,17 @@ Element::GetElementsByTagNameNS(const ns
   return NS_OK;
 }
 
 bool
 Element::HasAttributeNS(const nsAString& aNamespaceURI,
                         const nsAString& aLocalName) const
 {
   int32_t nsid =
-    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
+    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI, OwnerDoc());
 
   if (nsid == kNameSpaceID_Unknown) {
     // Unknown namespace means no attr...
     return false;
   }
 
   nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
   return HasAttr(nsid, name);
--- a/dom/base/NameSpaceConstants.h
+++ b/dom/base/NameSpaceConstants.h
@@ -18,11 +18,12 @@ static const int32_t kNameSpaceID_None =
 #define kNameSpaceID_XHTML    3
 #define kNameSpaceID_XLink    4
 #define kNameSpaceID_XSLT     5
 #define kNameSpaceID_XBL      6
 #define kNameSpaceID_MathML   7
 #define kNameSpaceID_RDF      8
 #define kNameSpaceID_XUL      9
 #define kNameSpaceID_SVG      10
-#define kNameSpaceID_LastBuiltin          10 // last 'built-in' namespace
+#define kNameSpaceID_disabled_MathML      11
+#define kNameSpaceID_LastBuiltin          11 // last 'built-in' namespace
 
 #endif // mozilla_dom_NameSpaceConstants_h__
--- a/dom/base/NodeInfo.cpp
+++ b/dom/base/NodeInfo.cpp
@@ -192,17 +192,18 @@ NodeInfo::GetNamespaceURI(nsAString& aNa
     SetDOMStringToNull(aNameSpaceURI);
   }
 }
 
 bool
 NodeInfo::NamespaceEquals(const nsAString& aNamespaceURI) const
 {
   int32_t nsid =
-    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
+    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
+      mOwnerManager->GetDocument());
 
   return mozilla::dom::NodeInfo::NamespaceEquals(nsid);
 }
 
 void
 NodeInfo::DeleteCycleCollectable()
 {
   RefPtr<nsNodeInfoManager> kungFuDeathGrip = mOwnerManager;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -2887,17 +2887,18 @@ nsContentUtils::SplitQName(const nsICont
     const char16_t* end;
     aQName.EndReading(end);
     nsAutoString nameSpace;
     rv = aNamespaceResolver->LookupNamespaceURIInternal(Substring(aQName.get(),
                                                                   colon),
                                                         nameSpace);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    *aNamespace = NameSpaceManager()->GetNameSpaceID(nameSpace);
+    *aNamespace = NameSpaceManager()->GetNameSpaceID(nameSpace,
+                                                     aNamespaceResolver->OwnerDoc());
     if (*aNamespace == kNameSpaceID_Unknown)
       return NS_ERROR_FAILURE;
 
     *aLocalName = NS_Atomize(Substring(colon + 1, end)).take();
   }
   else {
     *aNamespace = kNameSpaceID_None;
     *aLocalName = NS_Atomize(aQName).take();
--- a/dom/base/nsDOMAttributeMap.cpp
+++ b/dom/base/nsDOMAttributeMap.cpp
@@ -441,17 +441,18 @@ nsDOMAttributeMap::GetAttrNodeInfo(const
   if (!mContent) {
     return nullptr;
   }
 
   int32_t nameSpaceID = kNameSpaceID_None;
 
   if (!aNamespaceURI.IsEmpty()) {
     nameSpaceID =
-      nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
+      nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
+                                                         mContent->OwnerDoc());
 
     if (nameSpaceID == kNameSpaceID_Unknown) {
       return nullptr;
     }
   }
 
   uint32_t i, count = mContent->GetAttrCount();
   for (i = 0; i < count; ++i) {
--- a/dom/base/nsNameSpaceManager.cpp
+++ b/dom/base/nsNameSpaceManager.cpp
@@ -10,27 +10,35 @@
  */
 
 #include "nsNameSpaceManager.h"
 
 #include "nscore.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "nsCOMArray.h"
 #include "nsContentCreatorFunctions.h"
+#include "nsContentUtils.h"
 #include "nsGkAtoms.h"
+#include "nsIDocument.h"
 #include "nsString.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/XBLChildrenElement.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-StaticAutoPtr<nsNameSpaceManager> nsNameSpaceManager::sInstance;
+static const char* kPrefMathMLDisabled = "mathml.disabled";
+static const char* kObservedPrefs[] = {
+  kPrefMathMLDisabled,
+  nullptr
+};
+StaticRefPtr<nsNameSpaceManager> nsNameSpaceManager::sInstance;
 
 /* static */ nsNameSpaceManager*
 nsNameSpaceManager::GetInstance() {
   if (!sInstance) {
     sInstance = new nsNameSpaceManager();
     if (sInstance->Init()) {
       ClearOnShutdown(&sInstance);
     } else {
@@ -44,29 +52,39 @@ nsNameSpaceManager::GetInstance() {
 
 bool nsNameSpaceManager::Init()
 {
   nsresult rv;
 #define REGISTER_NAMESPACE(uri, id) \
   rv = AddNameSpace(dont_AddRef(uri), id); \
   NS_ENSURE_SUCCESS(rv, false)
 
+#define REGISTER_DISABLED_NAMESPACE(uri, id) \
+  rv = AddDisabledNameSpace(dont_AddRef(uri), id); \
+  NS_ENSURE_SUCCESS(rv, false)
+
+  mozilla::Preferences::AddStrongObservers(this, kObservedPrefs);
+  mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled);
+
+
   // Need to be ordered according to ID.
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xmlns, kNameSpaceID_XMLNS);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xml, kNameSpaceID_XML);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xhtml, kNameSpaceID_XHTML);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xlink, kNameSpaceID_XLink);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xslt, kNameSpaceID_XSLT);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xbl, kNameSpaceID_XBL);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_mathml, kNameSpaceID_MathML);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_rdf, kNameSpaceID_RDF);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xul, kNameSpaceID_XUL);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_svg, kNameSpaceID_SVG);
+  REGISTER_DISABLED_NAMESPACE(nsGkAtoms::nsuri_mathml, kNameSpaceID_disabled_MathML);
 
 #undef REGISTER_NAMESPACE
+#undef REGISTER_DISABLED_NAMESPACE
 
   return true;
 }
 
 nsresult
 nsNameSpaceManager::RegisterNameSpace(const nsAString& aURI,
                                       int32_t& aNameSpaceID)
 {
@@ -105,34 +123,42 @@ nsNameSpaceManager::GetNameSpaceURI(int3
   }
 
   mURIArray.ElementAt(index)->ToString(aURI);
 
   return NS_OK;
 }
 
 int32_t
-nsNameSpaceManager::GetNameSpaceID(const nsAString& aURI)
+nsNameSpaceManager::GetNameSpaceID(const nsAString& aURI,
+                                   nsIDocument* aDocument)
 {
   if (aURI.IsEmpty()) {
     return kNameSpaceID_None; // xmlns="", see bug 75700 for details
   }
 
   nsCOMPtr<nsIAtom> atom = NS_Atomize(aURI);
-  return GetNameSpaceID(atom);
+  return GetNameSpaceID(atom, aDocument);
 }
 
 int32_t
-nsNameSpaceManager::GetNameSpaceID(nsIAtom* aURI)
+nsNameSpaceManager::GetNameSpaceID(nsIAtom* aURI,
+                                   nsIDocument* aDocument)
 {
   if (aURI == nsGkAtoms::_empty) {
     return kNameSpaceID_None; // xmlns="", see bug 75700 for details
   }
 
   int32_t nameSpaceID;
+  if (mMathMLDisabled &&
+      mDisabledURIToIDTable.Get(aURI, &nameSpaceID) &&
+      !nsContentUtils::IsChromeDoc(aDocument)) {
+    NS_POSTCONDITION(nameSpaceID >= 0, "Bogus namespace ID");
+    return nameSpaceID;
+  }
   if (mURIToIDTable.Get(aURI, &nameSpaceID)) {
     NS_POSTCONDITION(nameSpaceID >= 0, "Bogus namespace ID");
     return nameSpaceID;
   }
 
   return kNameSpaceID_Unknown;
 }
 
@@ -148,17 +174,29 @@ NS_NewElement(Element** aResult,
     return NS_NewHTMLElement(aResult, ni.forget(), aFromParser, aIs);
   }
 #ifdef MOZ_XUL
   if (ns == kNameSpaceID_XUL) {
     return NS_NewXULElement(aResult, ni.forget());
   }
 #endif
   if (ns == kNameSpaceID_MathML) {
-    return NS_NewMathMLElement(aResult, ni.forget());
+    // If the mathml.disabled pref. is true, convert all MathML nodes into
+    // disabled MathML nodes by swapping the namespace.
+    nsNameSpaceManager* nsmgr = nsNameSpaceManager::GetInstance();
+    if ((nsmgr && !nsmgr->mMathMLDisabled) ||
+        nsContentUtils::IsChromeDoc(ni->GetDocument())) {
+      return NS_NewMathMLElement(aResult, ni.forget());
+    }
+
+    RefPtr<mozilla::dom::NodeInfo> genericXMLNI =
+      ni->NodeInfoManager()->
+      GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(),
+        kNameSpaceID_disabled_MathML, ni->NodeType(), ni->GetExtraName());
+    return NS_NewXMLElement(aResult, genericXMLNI.forget());
   }
   if (ns == kNameSpaceID_SVG) {
     return NS_NewSVGElement(aResult, ni.forget(), aFromParser);
   }
   if (ns == kNameSpaceID_XBL && ni->Equals(nsGkAtoms::children)) {
     NS_ADDREF(*aResult = new XBLChildrenElement(ni.forget()));
     return NS_OK;
   }
@@ -190,8 +228,40 @@ nsresult nsNameSpaceManager::AddNameSpac
   NS_ASSERTION(aNameSpaceID - 1 == (int32_t) mURIArray.Length(),
                "BAD! AddNameSpace not called in right order!");
 
   mURIArray.AppendElement(uri.forget());
   mURIToIDTable.Put(mURIArray.LastElement(), aNameSpaceID);
 
   return NS_OK;
 }
+
+nsresult
+nsNameSpaceManager::AddDisabledNameSpace(already_AddRefed<nsIAtom> aURI,
+                                         const int32_t aNameSpaceID)
+{
+  nsCOMPtr<nsIAtom> uri = aURI;
+  if (aNameSpaceID < 0) {
+    // We've wrapped...  Can't do anything else here; just bail.
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  NS_ASSERTION(aNameSpaceID - 1 == (int32_t) mURIArray.Length(),
+               "BAD! AddDisabledNameSpace not called in right order!");
+
+  mURIArray.AppendElement(uri.forget());
+  mDisabledURIToIDTable.Put(mURIArray.LastElement(), aNameSpaceID);
+
+  return NS_OK;
+}
+
+// nsISupports
+NS_IMPL_ISUPPORTS(nsNameSpaceManager,
+                  nsIObserver)
+
+// nsIObserver
+NS_IMETHODIMP
+nsNameSpaceManager::Observe(nsISupports* aObject, const char* aTopic,
+                            const char16_t* aMessage)
+{
+  mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled);
+  return NS_OK;
+}
--- a/dom/base/nsNameSpaceManager.h
+++ b/dom/base/nsNameSpaceManager.h
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsNameSpaceManager_h___
 #define nsNameSpaceManager_h___
 
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsIAtom.h"
+#include "nsIDocument.h"
+#include "nsIObserver.h"
 #include "nsTArray.h"
 
 #include "mozilla/StaticPtr.h"
 
 class nsAString;
 
 /**
  * The Name Space Manager tracks the association between a NameSpace
@@ -25,39 +27,47 @@ class nsAString;
  * consistent accross the app. NameSpace IDs are only consistent at runtime
  * ie: they are not guaranteed to be consistent accross app sessions.
  *
  * The nsNameSpaceManager needs to have a live reference for as long as
  * the NameSpace IDs are needed.
  *
  */
 
-class nsNameSpaceManager final
+class nsNameSpaceManager final : public nsIObserver
 {
 public:
-  ~nsNameSpaceManager() {}
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+  virtual nsresult RegisterNameSpace(const nsAString& aURI,
+                                     int32_t& aNameSpaceID);
 
-  nsresult RegisterNameSpace(const nsAString& aURI, int32_t& aNameSpaceID);
-
-  nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI);
+  virtual nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI);
 
   nsIAtom* NameSpaceURIAtom(int32_t aNameSpaceID) {
     MOZ_ASSERT(aNameSpaceID > 0 && (int64_t) aNameSpaceID <= (int64_t) mURIArray.Length());
     return mURIArray.ElementAt(aNameSpaceID - 1); // id is index + 1
   }
 
-  int32_t GetNameSpaceID(const nsAString& aURI);
-  int32_t GetNameSpaceID(nsIAtom* aURI);
+  int32_t GetNameSpaceID(const nsAString& aURI,
+                         nsIDocument* aDocument);
+  int32_t GetNameSpaceID(nsIAtom* aURI,
+                         nsIDocument* aDocument);
 
   bool HasElementCreator(int32_t aNameSpaceID);
 
   static nsNameSpaceManager* GetInstance();
+  bool mMathMLDisabled;
+
 private:
   bool Init();
   nsresult AddNameSpace(already_AddRefed<nsIAtom> aURI, const int32_t aNameSpaceID);
+  nsresult AddDisabledNameSpace(already_AddRefed<nsIAtom> aURI, const int32_t aNameSpaceID);
+  ~nsNameSpaceManager() {};
 
   nsDataHashtable<nsISupportsHashKey, int32_t> mURIToIDTable;
+  nsDataHashtable<nsISupportsHashKey, int32_t> mDisabledURIToIDTable;
   nsTArray<nsCOMPtr<nsIAtom>> mURIArray;
 
-  static mozilla::StaticAutoPtr<nsNameSpaceManager> sInstance;
+  static mozilla::StaticRefPtr<nsNameSpaceManager> sInstance;
 };
  
 #endif // nsNameSpaceManager_h___
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -344,16 +344,25 @@ SVGAnimationElement::UnsetAttr(int32_t a
 
 bool
 SVGAnimationElement::IsNodeOfType(uint32_t aFlags) const
 {
   return !(aFlags & ~(eCONTENT | eANIMATION));
 }
 
 //----------------------------------------------------------------------
+// SVGTests methods
+
+bool
+SVGAnimationElement::IsInChromeDoc() const
+{
+  return nsContentUtils::IsChromeDoc(OwnerDoc());
+}
+
+//----------------------------------------------------------------------
 // SVG utility methods
 
 void
 SVGAnimationElement::ActivateByHyperlink()
 {
   FlushAnimations();
 
   // The behavior for when the target is an animation element is defined in
--- a/dom/svg/SVGAnimationElement.h
+++ b/dom/svg/SVGAnimationElement.h
@@ -81,16 +81,20 @@ public:
   float GetStartTime(ErrorResult& rv);
   float GetCurrentTime();
   float GetSimpleDuration(ErrorResult& rv);
   void BeginElement(ErrorResult& rv) { BeginElementAt(0.f, rv); }
   void BeginElementAt(float offset, ErrorResult& rv);
   void EndElement(ErrorResult& rv) { EndElementAt(0.f, rv); }
   void EndElementAt(float offset, ErrorResult& rv);
 
+  // SVGTests
+  virtual bool IsInChromeDoc() const override;
+
+
  protected:
   // nsSVGElement overrides
 
   void UpdateHrefTarget(nsIContent* aNodeForContext,
                         const nsAString& aHrefStr);
   void AnimationTargetChanged();
 
   class TargetReference : public nsReferencedElement {
--- a/dom/svg/SVGGraphicsElement.cpp
+++ b/dom/svg/SVGGraphicsElement.cpp
@@ -26,10 +26,16 @@ SVGGraphicsElement::SVGGraphicsElement(a
   : SVGGraphicsElementBase(aNodeInfo)
 {
 }
 
 SVGGraphicsElement::~SVGGraphicsElement()
 {
 }
 
+bool
+SVGGraphicsElement::IsInChromeDoc() const
+{
+  return nsContentUtils::IsChromeDoc(OwnerDoc());
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/svg/SVGGraphicsElement.h
+++ b/dom/svg/SVGGraphicsElement.h
@@ -20,14 +20,16 @@ class SVGGraphicsElement : public SVGGra
 {
 protected:
   explicit SVGGraphicsElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   ~SVGGraphicsElement();
 
 public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
+
+  bool IsInChromeDoc() const override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGGraphicsElement_h
--- a/dom/svg/SVGSymbolElement.cpp
+++ b/dom/svg/SVGSymbolElement.cpp
@@ -76,16 +76,26 @@ SVGSymbolElement::IsAttributeMapped(cons
     sViewportsMap
    };
 
   return FindAttributeDependence(name, map) ||
     SVGSymbolElementBase::IsAttributeMapped(name);
 }
 
 //----------------------------------------------------------------------
+// SVGTests methods
+
+bool
+SVGSymbolElement::IsInChromeDoc() const
+{
+  return nsContentUtils::IsChromeDoc(OwnerDoc());
+}
+
+
+//----------------------------------------------------------------------
 // nsSVGElement methods
 
 nsSVGViewBox *
 SVGSymbolElement::GetViewBox()
 {
   return &mViewBox;
 }
 
--- a/dom/svg/SVGSymbolElement.h
+++ b/dom/svg/SVGSymbolElement.h
@@ -39,16 +39,19 @@ public:
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedRect> ViewBox();
   already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
 
+  // SVGTests
+  bool IsInChromeDoc() const override;
+
 protected:
   virtual nsSVGViewBox *GetViewBox() override;
   virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio() override;
 
   nsSVGViewBox mViewBox;
   SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
 };
 
--- a/dom/svg/SVGTests.cpp
+++ b/dom/svg/SVGTests.cpp
@@ -52,17 +52,17 @@ SVGTests::SystemLanguage()
   nsSVGElement* element = static_cast<nsSVGElement*>(elem.get());
   return DOMSVGStringList::GetDOMWrapper(
            &mStringListAttributes[LANGUAGE], element, true, LANGUAGE);
 }
 
 bool
 SVGTests::HasExtension(const nsAString& aExtension)
 {
-  return nsSVGFeatures::HasExtension(aExtension);
+  return nsSVGFeatures::HasExtension(aExtension, IsInChromeDoc());
 }
 
 bool
 SVGTests::IsConditionalProcessingAttribute(const nsIAtom* aAttribute) const
 {
   for (uint32_t i = 0; i < ArrayLength(sStringListNames); i++) {
     if (aAttribute == *sStringListNames[i]) {
       return true;
@@ -134,17 +134,17 @@ SVGTests::PassesConditionalProcessingTes
   // go beyond the feature set defined in the SVG specification.
   // Each extension is identified by a URI reference.
   // For now, claim that mozilla's SVG implementation supports XHTML and MathML.
   if (mStringListAttributes[EXTENSIONS].IsExplicitlySet()) {
     if (mStringListAttributes[EXTENSIONS].IsEmpty()) {
       return false;
     }
     for (uint32_t i = 0; i < mStringListAttributes[EXTENSIONS].Length(); i++) {
-      if (!nsSVGFeatures::HasExtension(mStringListAttributes[EXTENSIONS][i])) {
+      if (!nsSVGFeatures::HasExtension(mStringListAttributes[EXTENSIONS][i], IsInChromeDoc())) {
         return false;
       }
     }
   }
 
   if (aAcceptLangs == kIgnoreSystemLanguage) {
     return true;
   }
--- a/dom/svg/SVGTests.h
+++ b/dom/svg/SVGTests.h
@@ -90,16 +90,18 @@ public:
   void MaybeInvalidate();
 
   // WebIDL
   already_AddRefed<DOMSVGStringList> RequiredFeatures();
   already_AddRefed<DOMSVGStringList> RequiredExtensions();
   already_AddRefed<DOMSVGStringList> SystemLanguage();
   bool HasExtension(const nsAString& aExtension);
 
+  virtual bool IsInChromeDoc() const = 0;
+
 protected:
   virtual ~SVGTests() {}
 
 private:
   enum { FEATURES, EXTENSIONS, LANGUAGE };
   SVGStringList mStringListAttributes[3];
   static nsIAtom** sStringListNames[3];
 };
--- a/dom/svg/nsSVGFeatures.cpp
+++ b/dom/svg/nsSVGFeatures.cpp
@@ -10,16 +10,17 @@
  * requiredFeatures, requiredExtensions and systemLanguage attributes).
  *
  *   http://www.w3.org/TR/SVG11/struct.html#ConditionalProcessing
  */
 
 #include "nsSVGFeatures.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
+#include "nsNameSpaceManager.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 /*static*/ bool
 nsSVGFeatures::HasFeature(nsISupports* aObject, const nsAString& aFeature)
 {
   if (aFeature.EqualsLiteral("http://www.w3.org/TR/SVG11/feature#Script")) {
@@ -37,17 +38,20 @@ nsSVGFeatures::HasFeature(nsISupports* a
 #define SVG_UNSUPPORTED_FEATURE(str)
 #include "nsSVGFeaturesList.h"
 #undef SVG_SUPPORTED_FEATURE
 #undef SVG_UNSUPPORTED_FEATURE
   return false;
 }
 
 /*static*/ bool
-nsSVGFeatures::HasExtension(const nsAString& aExtension)
+nsSVGFeatures::HasExtension(const nsAString& aExtension, const bool aIsInChrome)
 {
 #define SVG_SUPPORTED_EXTENSION(str) if (aExtension.EqualsLiteral(str)) return true;
   SVG_SUPPORTED_EXTENSION("http://www.w3.org/1999/xhtml")
-  SVG_SUPPORTED_EXTENSION("http://www.w3.org/1998/Math/MathML")
+  nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
+  if (aIsInChrome || !nameSpaceManager->mMathMLDisabled) {
+    SVG_SUPPORTED_EXTENSION("http://www.w3.org/1998/Math/MathML")
+  }
 #undef SVG_SUPPORTED_EXTENSION
 
   return false;
 }
--- a/dom/svg/nsSVGFeatures.h
+++ b/dom/svg/nsSVGFeatures.h
@@ -25,12 +25,12 @@ public:
 
   /**
    * Check whether we support the given extension string.
    *
    * @param aExtension the URI of an extension. Known extensions are
    *   "http://www.w3.org/1999/xhtml" and "http://www.w3.org/1998/Math/MathML"
    */
   static bool
-  HasExtension(const nsAString& aExtension);
+  HasExtension(const nsAString& aExtension, const bool aIsInChrome);
 };
 
 #endif // __NS_SVGFEATURES_H__
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -1594,17 +1594,17 @@ nsXBLPrototypeBinding::ResolveBaseBindin
   }
 
   nsAutoString nameSpace;
 
   if (!prefix.IsEmpty()) {
     mBinding->LookupNamespaceURI(prefix, nameSpace);
     if (!nameSpace.IsEmpty()) {
       int32_t nameSpaceID =
-        nsContentUtils::NameSpaceManager()->GetNameSpaceID(nameSpace);
+        nsContentUtils::NameSpaceManager()->GetNameSpaceID(nameSpace, doc);
 
       nsCOMPtr<nsIAtom> tagName = NS_Atomize(display);
       // Check the white list
       if (!CheckTagNameWhiteList(nameSpaceID, tagName)) {
         const char16_t* params[] = { display.get() };
         nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
                                         NS_LITERAL_CSTRING("XBL"), nullptr,
                                         nsContentUtils::eXBL_PROPERTIES,
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -1044,16 +1044,19 @@ nsXMLContentSink::HandleEndElement(const
                                  getter_AddRefs(debugTagAtom),
                                  &debugNameSpaceID);
   // Check if we are closing a template element because template
   // elements do not get pushed on the stack, the template
   // element content is pushed instead.
   bool isTemplateElement = debugTagAtom == nsGkAtoms::_template &&
                            debugNameSpaceID == kNameSpaceID_XHTML;
   NS_ASSERTION(content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID) ||
+               (debugNameSpaceID == kNameSpaceID_MathML &&
+                content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_MathML &&
+                content->NodeInfo()->Equals(debugTagAtom)) ||
                isTemplateElement, "Wrong element being closed");
 #endif
 
   result = CloseElement(content);
 
   if (mCurrentHead == content) {
     mCurrentHead = nullptr;
   }
--- a/layout/mathml/moz.build
+++ b/layout/mathml/moz.build
@@ -7,16 +7,19 @@
 with Files('**'):
     BUG_COMPONENT = ('Core', 'MathML')
 
 if CONFIG['ENABLE_TESTS']:
     MOCHITEST_MANIFESTS += [
         'imptests/mochitest.ini',
         'tests/mochitest.ini',
 ]
+    MOCHITEST_CHROME_MANIFESTS += [
+        'tests/chrome.ini',
+]
 
 UNIFIED_SOURCES += [
     'nsMathMLChar.cpp',
     'nsMathMLContainerFrame.cpp',
     'nsMathMLFrame.cpp',
     'nsMathMLmactionFrame.cpp',
     'nsMathMLmencloseFrame.cpp',
     'nsMathMLmfencedFrame.cpp',
new file mode 100644
--- /dev/null
+++ b/layout/mathml/tests/chrome.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+
+support-files =
+  mathml_example_test.html
+
+[test_disabled_chrome.html]
new file mode 100644
--- /dev/null
+++ b/layout/mathml/tests/mathml_example_test.html
@@ -0,0 +1,28 @@
+<math xmlns="http://www.w3.org/1998/Math/MathML">
+  <mstyle scriptsizemultiplier="2">
+    <msub>
+      <mtext>O</mtext>
+      <mtext>O</mtext>
+    </msub>
+    <msup>
+      <mtext>O</mtext>
+      <mtext>O</mtext>
+    </msup>
+    <msubsup>
+      <mtext>O</mtext>
+      <mtext>O</mtext>
+      <mtext>O</mtext>
+    </msubsup>
+    <mmultiscripts>
+      <mtext>O</mtext>
+      <mtext>O</mtext>
+      <mtext>O</mtext>
+      <mprescripts/>
+      <mtext>O</mtext>
+      <mtext>O</mtext>
+    </mmultiscripts>
+  </mstyle>
+</math>
+
+<svg id="svgel">
+</svg>
--- a/layout/mathml/tests/mochitest.ini
+++ b/layout/mathml/tests/mochitest.ini
@@ -1,16 +1,17 @@
 [DEFAULT]
 
 [test_bug330964.html]
 [test_bug553917.html]
 [test_bug706406.html]
 [test_bug827713-2.html]
 [test_bug827713.html]
 [test_bug975681.html]
+[test_disabled.html]
 [test_opentype-axis-height.html]
 [test_opentype-fraction.html]
 [test_opentype-limits.html]
 skip-if = os == "win" # Fails on WinXP
 [test_opentype-radical.html]
 skip-if = os == "win" # Fails on WinXP
 [test_opentype-scripts.html]
 [test_opentype-stack.html]
new file mode 100644
--- /dev/null
+++ b/layout/mathml/tests/test_disabled.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Copied from
+https://bugzilla.mozilla.org/show_bug.cgi?id=744830
+-->
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=166235">Mozilla Bug 166235</a>
+<div id="testnodes"><span>hi</span> there <!-- mon ami --></div>
+<pre id="test">
+<script type="application/javascript">
+  SimpleTest.waitForExplicitFinish();
+  SpecialPowers.pushPrefEnv({"set": [["mathml.disabled", true]]}, doTest);
+  function doTest() {
+    let t = document.getElementById('testnodes');
+    t.innerHTML = null;
+    t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math:math"));
+    t.firstChild.textContent = "<foo>";
+    is(t.innerHTML, "<math:math>&lt;foo&gt;</math:math>");
+
+    t.innerHTML = null;
+    t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math"));
+    is(t.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
+    t.firstChild.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "script"));
+    is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
+    t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
+    is(t.innerHTML, '<math><script>1&amp;2&lt;3&gt;4&nbsp;\u003C/script></math>');
+
+    t.innerHTML = null;
+    t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math"));
+    is(t.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
+    t.firstChild.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "style"));
+    is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
+    t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
+    is(t.innerHTML, '<math><style>1&amp;2&lt;3&gt;4&nbsp;\u003C/style></math>');
+
+    SimpleTest.finish();
+  }
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/mathml/tests/test_disabled_chrome.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=744830
+-->
+<head>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<!--
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+-->
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=166235">Mozilla Bug 166235</a>
+<div id="testnodes"><span>hi</span> there <!-- mon ami --></div>
+<pre id="test">
+<script type="application/javascript">
+  add_task(function* () {
+    const initialPrefValue = SpecialPowers.getBoolPref("mathml.disabled");
+    SpecialPowers.setBoolPref("mathml.disabled", true);
+    const Cu = SpecialPowers.Components.utils;
+    const { ContentTaskUtils } = Cu.import("resource://testing-common/ContentTaskUtils.jsm", {});
+    let t = document.getElementById('testnodes');
+
+    let url = 'chrome://mochitests/content/chrome/layout/mathml/tests/mathml_example_test.html'
+    const chromeIframeEl = document.createElement('iframe');
+    let chromeLoadPromise = ContentTaskUtils.waitForEvent(chromeIframeEl, 'load', false);
+    chromeIframeEl.src = url;
+    t.appendChild(chromeIframeEl);
+
+    yield chromeLoadPromise;
+    const chromeBR = chromeIframeEl.contentDocument.body.getBoundingClientRect();
+
+    url = "http://mochi.test:8888/chrome/layout/mathml/tests/mathml_example_test.html";
+    const iframeEl = document.createElement('iframe');
+    iframeEl.src = url;
+    let loadPromise = ContentTaskUtils.waitForEvent(iframeEl, 'load', false);
+    t.appendChild(iframeEl);
+    yield loadPromise;
+
+    const contentBR = iframeEl.contentDocument.body.getBoundingClientRect();
+
+    ok(chromeBR.height > contentBR.height, "Chrome content height should be bigger than content due to layout");
+
+    ok(!iframeEl.contentDocument.getElementById('svgel').hasExtension("http://www.w3.org/1998/Math/MathML"), 'SVG namespace support is disabled in content iframe');
+    ok(chromeIframeEl.contentDocument.getElementById('svgel').hasExtension("http://www.w3.org/1998/Math/MathML"), 'SVG namespace support is enabled in chrome iframe');
+
+    SpecialPowers.setBoolPref("mathml.disabled", initialPrefValue);
+  });
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/disabled-scriptlevel-1-ref.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>scriptlevel</title>
+    <meta charset="utf-8"/>
+  </head>
+  <body>
+
+    <!-- Test scriptlevel on mstyle -->
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <mtext>O</mtext>
+        <mstyle scriptlevel="1"><mtext>O</mtext></mstyle>
+      </mstyle>
+    </randomelement>
+
+    <!-- The mfrac element sets displaystyle to "false", or if it was already
+         false increments scriptlevel by 1, within numerator and denominator.
+      -->
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <mstyle displaystyle="false">
+          <mfrac>
+            <mtext>O</mtext>
+            <mtext>O</mtext>
+          </mfrac>
+        </mstyle>
+        <mstyle displaystyle="true">
+          <mfrac>
+            <mtext>O</mtext>
+            <mtext>O</mtext>
+          </mfrac>
+        </mstyle>
+      </mstyle>
+    </randomelement>
+
+    <!--    The mroot element increments scriptlevel by 2, and sets
+            displaystyle to "false", within index, but leaves both attributes
+            unchanged within base.
+            The msqrt element leaves both attributes unchanged within its
+            argument. -->
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <mroot>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mroot>
+        <msqrt>
+          <mtext>O</mtext>
+        </msqrt>
+      </mstyle>
+    </randomelement>
+
+<!--
+    The msub element [...] increments scriptlevel by 1, and sets displaystyle to
+   "false", within subscript, but leaves both attributes unchanged within base.
+
+   The msup element [...] increments scriptlevel by 1, and sets displaystyle to
+   "false", within superscript, but leaves both attributes unchanged within
+   base.
+
+   The msubsup element [...] increments scriptlevel by 1, and sets displaystyle
+   to "false", within subscript and superscript, but leaves both attributes
+   unchanged within base.
+
+   The mmultiscripts element increments scriptlevel by 1, and sets displaystyle
+   to "false", within each of its arguments except base, but leaves both
+   attributes unchanged within base.
+   -->
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <msub>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msub>
+        <msup>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msup>
+        <msubsup>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msubsup>
+        <mmultiscripts>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mprescripts/>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mmultiscripts>
+      </mstyle>
+    </randomelement>
+
+<!-- 
+   The munder element [...] always sets displaystyle to "false" within the
+   underscript, but increments scriptlevel by 1 only when accentunder is
+   "false". Within base, it always leaves both attributes unchanged.
+
+   The mover element [...] always sets displaystyle to "false" within
+   overscript, but increments scriptlevel by 1 only when accent is "false".
+   Within base, it always leaves both attributes unchanged.
+
+   The munderover [..] always sets displaystyle to "false" within underscript
+   and overscript, but increments scriptlevel by 1 only when accentunder or
+   accent, respectively, are "false". Within base, it always leaves both
+   attributes unchanged.
+-->   
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <munder>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </munder>
+        <mover>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mover>
+        <munderover>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </munderover>
+      </mstyle>
+    </randomelement>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/disabled-scriptlevel-1-ref.xhtml
@@ -0,0 +1,133 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>scriptlevel</title>
+    <meta charset="utf-8"/>
+    <style>
+      h2 {
+        text-align:center;
+      }
+    </style>
+  </head>
+  <body>
+
+    <!-- Test scriptlevel on mstyle -->
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <mtext>O</mtext>
+        <mstyle scriptlevel="1"><mtext>O</mtext></mstyle>
+      </mstyle>
+    </randomelement>
+
+    <!-- The mfrac element sets displaystyle to "false", or if it was already
+         false increments scriptlevel by 1, within numerator and denominator.
+      -->
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <mstyle displaystyle="false">
+          <mfrac>
+            <mtext>O</mtext>
+            <mtext>O</mtext>
+          </mfrac>
+        </mstyle>
+        <mstyle displaystyle="true">
+          <mfrac>
+            <mtext>O</mtext>
+            <mtext>O</mtext>
+          </mfrac>
+        </mstyle>
+      </mstyle>
+    </randomelement>
+
+    <!--    The mroot element increments scriptlevel by 2, and sets
+            displaystyle to "false", within index, but leaves both attributes
+            unchanged within base.
+            The msqrt element leaves both attributes unchanged within its
+            argument. -->
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <mroot>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mroot>
+        <msqrt>
+          <mtext>O</mtext>
+        </msqrt>
+      </mstyle>
+    </randomelement>
+
+<!--
+    The msub element [...] increments scriptlevel by 1, and sets displaystyle to
+   "false", within subscript, but leaves both attributes unchanged within base.
+
+   The msup element [...] increments scriptlevel by 1, and sets displaystyle to
+   "false", within superscript, but leaves both attributes unchanged within
+   base.
+
+   The msubsup element [...] increments scriptlevel by 1, and sets displaystyle
+   to "false", within subscript and superscript, but leaves both attributes
+   unchanged within base.
+
+   The mmultiscripts element increments scriptlevel by 1, and sets displaystyle
+   to "false", within each of its arguments except base, but leaves both
+   attributes unchanged within base.
+   -->
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <msub>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msub>
+        <msup>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msup>
+        <msubsup>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msubsup>
+        <mmultiscripts>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mprescripts/>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mmultiscripts>
+      </mstyle>
+    </randomelement>
+
+<!-- 
+   The munder element [...] always sets displaystyle to "false" within the
+   underscript, but increments scriptlevel by 1 only when accentunder is
+   "false". Within base, it always leaves both attributes unchanged.
+
+   The mover element [...] always sets displaystyle to "false" within
+   overscript, but increments scriptlevel by 1 only when accent is "false".
+   Within base, it always leaves both attributes unchanged.
+
+   The munderover [..] always sets displaystyle to "false" within underscript
+   and overscript, but increments scriptlevel by 1 only when accentunder or
+   accent, respectively, are "false". Within base, it always leaves both
+   attributes unchanged.
+-->   
+    <randomelement>
+      <mstyle scriptsizemultiplier="2">
+        <munder>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </munder>
+        <mover>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mover>
+        <munderover>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </munderover>
+      </mstyle>
+    </randomelement>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/disabled-scriptlevel-1.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>scriptlevel</title>
+    <meta charset="utf-8"/>
+  </head>
+  <body>
+
+    <!-- Test scriptlevel on mstyle -->
+    <math>
+      <mstyle scriptsizemultiplier="2">
+        <mtext>O</mtext>
+        <mstyle scriptlevel="1"><mtext>O</mtext></mstyle>
+      </mstyle>
+    </math>
+
+    <!-- The mfrac element sets displaystyle to "false", or if it was already
+         false increments scriptlevel by 1, within numerator and denominator.
+      -->
+    <math>
+      <mstyle scriptsizemultiplier="2">
+        <mstyle displaystyle="false">
+          <mfrac>
+            <mtext>O</mtext>
+            <mtext>O</mtext>
+          </mfrac>
+        </mstyle>
+        <mstyle displaystyle="true">
+          <mfrac>
+            <mtext>O</mtext>
+            <mtext>O</mtext>
+          </mfrac>
+        </mstyle>
+      </mstyle>
+    </math>
+
+    <!--    The mroot element increments scriptlevel by 2, and sets
+            displaystyle to "false", within index, but leaves both attributes
+            unchanged within base.
+            The msqrt element leaves both attributes unchanged within its
+            argument. -->
+    <math>
+      <mstyle scriptsizemultiplier="2">
+        <mroot>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mroot>
+        <msqrt>
+          <mtext>O</mtext>
+        </msqrt>
+      </mstyle>
+    </math>
+
+<!--
+    The msub element [...] increments scriptlevel by 1, and sets displaystyle to
+   "false", within subscript, but leaves both attributes unchanged within base.
+
+   The msup element [...] increments scriptlevel by 1, and sets displaystyle to
+   "false", within superscript, but leaves both attributes unchanged within
+   base.
+
+   The msubsup element [...] increments scriptlevel by 1, and sets displaystyle
+   to "false", within subscript and superscript, but leaves both attributes
+   unchanged within base.
+
+   The mmultiscripts element increments scriptlevel by 1, and sets displaystyle
+   to "false", within each of its arguments except base, but leaves both
+   attributes unchanged within base.
+   -->
+    <math>
+      <mstyle scriptsizemultiplier="2">
+        <msub>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msub>
+        <msup>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msup>
+        <msubsup>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msubsup>
+        <mmultiscripts>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mprescripts/>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mmultiscripts>
+      </mstyle>
+    </math>
+
+<!-- 
+   The munder element [...] always sets displaystyle to "false" within the
+   underscript, but increments scriptlevel by 1 only when accentunder is
+   "false". Within base, it always leaves both attributes unchanged.
+
+   The mover element [...] always sets displaystyle to "false" within
+   overscript, but increments scriptlevel by 1 only when accent is "false".
+   Within base, it always leaves both attributes unchanged.
+
+   The munderover [..] always sets displaystyle to "false" within underscript
+   and overscript, but increments scriptlevel by 1 only when accentunder or
+   accent, respectively, are "false". Within base, it always leaves both
+   attributes unchanged.
+-->   
+    <math>
+      <mstyle scriptsizemultiplier="2">
+        <munder>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </munder>
+        <mover>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mover>
+        <munderover>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </munderover>
+      </mstyle>
+    </math>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/disabled-scriptlevel-1.xhtml
@@ -0,0 +1,133 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>scriptlevel</title>
+    <meta charset="utf-8"/>
+    <style>
+      h2 {
+        text-align:center;
+      }
+    </style>
+  </head>
+  <body>
+
+    <!-- Test scriptlevel on mstyle -->
+    <math xmlns="http://www.w3.org/1998/Math/MathML">
+      <mstyle scriptsizemultiplier="2">
+        <mtext>O</mtext>
+        <mstyle scriptlevel="1"><mtext>O</mtext></mstyle>
+      </mstyle>
+    </math>
+
+    <!-- The mfrac element sets displaystyle to "false", or if it was already
+         false increments scriptlevel by 1, within numerator and denominator.
+      -->
+    <math xmlns="http://www.w3.org/1998/Math/MathML">
+      <mstyle scriptsizemultiplier="2">
+        <mstyle displaystyle="false">
+          <mfrac>
+            <mtext>O</mtext>
+            <mtext>O</mtext>
+          </mfrac>
+        </mstyle>
+        <mstyle displaystyle="true">
+          <mfrac>
+            <mtext>O</mtext>
+            <mtext>O</mtext>
+          </mfrac>
+        </mstyle>
+      </mstyle>
+    </math>
+
+    <!--    The mroot element increments scriptlevel by 2, and sets
+            displaystyle to "false", within index, but leaves both attributes
+            unchanged within base.
+            The msqrt element leaves both attributes unchanged within its
+            argument. -->
+    <math xmlns="http://www.w3.org/1998/Math/MathML">
+      <mstyle scriptsizemultiplier="2">
+        <mroot>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mroot>
+        <msqrt>
+          <mtext>O</mtext>
+        </msqrt>
+      </mstyle>
+    </math>
+
+<!--
+    The msub element [...] increments scriptlevel by 1, and sets displaystyle to
+   "false", within subscript, but leaves both attributes unchanged within base.
+
+   The msup element [...] increments scriptlevel by 1, and sets displaystyle to
+   "false", within superscript, but leaves both attributes unchanged within
+   base.
+
+   The msubsup element [...] increments scriptlevel by 1, and sets displaystyle
+   to "false", within subscript and superscript, but leaves both attributes
+   unchanged within base.
+
+   The mmultiscripts element increments scriptlevel by 1, and sets displaystyle
+   to "false", within each of its arguments except base, but leaves both
+   attributes unchanged within base.
+   -->
+    <math xmlns="http://www.w3.org/1998/Math/MathML">
+      <mstyle scriptsizemultiplier="2">
+        <msub>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msub>
+        <msup>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msup>
+        <msubsup>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </msubsup>
+        <mmultiscripts>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mprescripts/>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mmultiscripts>
+      </mstyle>
+    </math>
+
+<!-- 
+   The munder element [...] always sets displaystyle to "false" within the
+   underscript, but increments scriptlevel by 1 only when accentunder is
+   "false". Within base, it always leaves both attributes unchanged.
+
+   The mover element [...] always sets displaystyle to "false" within
+   overscript, but increments scriptlevel by 1 only when accent is "false".
+   Within base, it always leaves both attributes unchanged.
+
+   The munderover [..] always sets displaystyle to "false" within underscript
+   and overscript, but increments scriptlevel by 1 only when accentunder or
+   accent, respectively, are "false". Within base, it always leaves both
+   attributes unchanged.
+-->   
+    <math xmlns="http://www.w3.org/1998/Math/MathML">
+      <mstyle scriptsizemultiplier="2">
+        <munder>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </munder>
+        <mover>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </mover>
+        <munderover>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+          <mtext>O</mtext>
+        </munderover>
+      </mstyle>
+    </math>
+
+  </body>
+</html>
--- a/layout/reftests/mathml/reftest.list
+++ b/layout/reftests/mathml/reftest.list
@@ -6,16 +6,18 @@
 == dir-6.html dir-6-ref.html
 == dir-6a.html dir-6a-ref.html
 == dir-7.html dir-7-ref.html
 fails == dir-8.html dir-8-ref.html
 fails == dir-9.html dir-9-ref.html # Bug 787215
 == dir-10.html dir-10-ref.html
 random-if((B2G&&browserIsRemote)||Mulet) == dir-11.html dir-11-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 == css-spacing-1.html css-spacing-1-ref.html
+pref(mathml.disabled,true) == disabled-scriptlevel-1.html disabled-scriptlevel-1-ref.html
+pref(mathml.disabled,true) == disabled-scriptlevel-1.xhtml disabled-scriptlevel-1-ref.xhtml
 == displaystyle-1.html displaystyle-1-ref.html
 == displaystyle-2.html displaystyle-2-ref.html
 == displaystyle-3.html displaystyle-3-ref.html
 random-if((B2G&&browserIsRemote)||Mulet) == displaystyle-4.html displaystyle-4-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) random-if(smallScreen&&Android) fuzzy(255,200) == mirror-op-1.html mirror-op-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 != mirror-op-2.html mirror-op-2-ref.html
 != mirror-op-3.html mirror-op-3-ref.html
 != mirror-op-4.html mirror-op-4-ref.html
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -227,17 +227,18 @@ AtomAttrValue(Implementor* aElement, nsI
   return attr ? attr->GetAtomValue() : nullptr;
 }
 
 template <typename Implementor, typename MatchFn>
 static bool
 DoMatch(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, MatchFn aMatch)
 {
   if (aNS) {
-    int32_t ns = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNS);
+    int32_t ns = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNS,
+                                                                    aElement->OwnerDoc());
     NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, false);
     const nsAttrValue* value = aElement->GetParsedAttr(aName, ns);
     return value && aMatch(value);
   }
   // No namespace means any namespace - we have to check them all. :-(
   BorrowedAttrInfo attrInfo;
   for (uint32_t i = 0; (attrInfo = aElement->GetAttrInfoAt(i)); ++i) {
     if (attrInfo.mName->LocalName() != aName) {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -275,16 +275,19 @@ pref("browser.chrome.image_icons.max_siz
 pref("browser.triple_click_selects_paragraph", true);
 
 // Print/Preview Shrink-To-Fit won't shrink below 20% for text-ish documents.
 pref("print.shrink-to-fit.scale-limit-percent", 20);
 
 // Whether we should display simplify page checkbox on print preview UI
 pref("print.use_simplify_page", false);
 
+// Disable support for MathML
+pref("mathml.disabled",    false);
+
 // Enable scale transform for stretchy MathML operators. See bug 414277.
 pref("mathml.scale_stretchy_operators.enabled", true);
 
 // Media cache size in kilobytes
 pref("media.cache_size", 512000);
 // When a network connection is suspended, don't resume it until the
 // amount of buffered data falls below this threshold (in seconds).
 pref("media.cache_resume_threshold", 999999);
--- a/testing/web-platform/mozilla/meta/MANIFEST.json
+++ b/testing/web-platform/mozilla/meta/MANIFEST.json
@@ -4,16 +4,25 @@
     "reftest": [],
     "stub": [],
     "testharness": [],
     "wdspec": []
   },
   "local_changes": {
     "deleted": [],
     "deleted_reftests": {},
-    "items": {},
+    "items": {
+      "testharness": {
+        "html/syntax/parsing/math-parse01.html": [
+          {
+            "path": "html/syntax/parsing/math-parse01.html",
+            "url": "/html/syntax/parsing/math-parse01.html"
+          }
+        ]
+      }
+    },
     "reftest_nodes": {}
   },
   "reftest_nodes": {},
   "rev": null,
   "url_base": "/_mozilla/",
   "version": 3
 }
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/html/syntax/parsing/math-parse01.html.ini
@@ -0,0 +1,2 @@
+[math-parse01.html]
+  prefs: ["mathml.disabled:true"]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/parsing/math-parse01.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>math in html: parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>math in html: parsing</h1>
+
+<div id="log" style="display:block"></div>
+
+<div style="display:none">
+<div><math id="m1"><mtext/></math></div>
+<div id="d1"><math><mrow/><mi/></math></div>
+<div id="d2"><math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math></div>
+<div id="d3">&lang;&rang;</div>
+<div id="d4">&Kopf;</div>
+<div id="d5"><math><semantics><mi>a</mi><annotation-xml><foo/><bar/></annotation-xml></semantics></math></div>
+<div id="d6"><math><semantics><mi>a</mi><annotation-xml encoding="text/html"><div></div></annotation-xml></semantics><mn/></math>
+</div>
+
+
+<script>
+
+test(function() {
+assert_equals(document.getElementById("m1"),document.getElementsByTagName("math")[0]);
+},"The id attribute should be recognised on math elements");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.nodeName,"math")
+},"The node name should be math");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.namespaceURI ,"http://www.w3.org/1998/Math/MathML")
+},"math should be in MathML Namespace");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.childNodes.length ,2)
+},"Math has 2 children (empty tag syntax)");
+
+test(function() {
+assert_equals(document.getElementById("d2").firstChild.childNodes.length ,1)
+},"Nested mrow elements should be parsed correctly");
+
+test(function() {
+assert_equals(document.getElementById("d3").firstChild.nodeValue ,"\u27E8\u27E9")
+},"Testing rang and lang entity code points");
+
+test(function() {
+assert_equals(document.getElementById("d4").firstChild.nodeValue ,"\uD835\uDD42")
+},"Testing Kopf (Plane 1) entity code point");
+
+test(function() {
+assert_equals(document.getElementById("d5").firstChild.firstChild.childNodes[1].childNodes.length ,2)
+},"Empty element tags in annotation-xml parsed as per XML.");
+
+test(function() {
+assert_equals(document.getElementById("d6").firstChild.childNodes.length ,2)
+},"html tags allowed in annotation-xml/@encoding='text/html'.");
+
+</script>