Bug 851892 part 13. Convert media, supports, and moz-document rules to WebIDL. r=peterv,heycam
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 13 Jan 2017 10:41:03 -0500
changeset 377717 336c0e3ea229cc82a8d5aa65ffc579c84de5115f
parent 377716 02bd976e715734b67a6c4c9e1300205c4e21f986
child 377718 c70e7a0b7d2904bc0e4722f8bd7baab5abf9b0e9
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv, heycam
bugs851892
milestone53.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 851892 part 13. Convert media, supports, and moz-document rules to WebIDL. r=peterv,heycam
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoID.h
dom/base/nsWrapperCache.h
dom/bindings/Bindings.conf
dom/webidl/CSSConditionRule.webidl
dom/webidl/CSSGroupingRule.webidl
dom/webidl/CSSMediaRule.webidl
dom/webidl/CSSMozDocumentRule.webidl
dom/webidl/CSSSupportsRule.webidl
dom/webidl/LegacyQueryInterface.webidl
dom/webidl/moz.build
layout/style/GroupRule.h
layout/style/nsCSSRules.cpp
layout/style/nsCSSRules.h
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -71,20 +71,17 @@
 // CSS related includes
 #include "nsCSSRules.h"
 #include "nsIDOMCSSRule.h"
 #include "nsMemory.h"
 
 // includes needed for the prototype chain interfaces
 #include "nsIDOMCSSKeyframeRule.h"
 #include "nsIDOMCSSKeyframesRule.h"
-#include "nsIDOMCSSMediaRule.h"
 #include "nsIDOMCSSFontFaceRule.h"
-#include "nsIDOMCSSMozDocumentRule.h"
-#include "nsIDOMCSSSupportsRule.h"
 #include "nsIDOMCSSCounterStyleRule.h"
 #include "nsIDOMCSSPageRule.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIControllers.h"
 #ifdef MOZ_XUL
 #include "nsITreeSelection.h"
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
@@ -182,21 +179,16 @@ static nsDOMClassInfoData sClassInfoData
                            nsIXPCScriptable::WANT_RESOLVE |
                            nsIXPCScriptable::WANT_HASINSTANCE |
                            nsIXPCScriptable::WANT_CALL |
                            nsIXPCScriptable::WANT_CONSTRUCT |
                            nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
 
   // Misc Core related classes
 
-  // CSS classes
-  NS_DEFINE_CLASSINFO_DATA(CSSMediaRule, nsCSSRuleSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS |
-                           nsIXPCScriptable::WANT_PRECREATE)
-
   // XUL classes
 #ifdef MOZ_XUL
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCommandDispatcher, nsDOMGenericSH,
                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULControllers, nsNonDOMObjectSH,
                                       DEFAULT_SCRIPTABLE_FLAGS)
 #ifdef MOZ_XUL
@@ -209,24 +201,16 @@ static nsDOMClassInfoData sClassInfoData
 #ifdef MOZ_XUL
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTemplateBuilder, nsDOMGenericSH,
                                       DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTreeBuilder, nsDOMGenericSH,
                                       DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
-  NS_DEFINE_CLASSINFO_DATA(CSSMozDocumentRule, nsCSSRuleSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS |
-                           nsIXPCScriptable::WANT_PRECREATE)
-
-  NS_DEFINE_CLASSINFO_DATA(CSSSupportsRule, nsCSSRuleSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS |
-                           nsIXPCScriptable::WANT_PRECREATE)
-
   NS_DEFINE_CLASSINFO_DATA(CSSFontFaceRule, nsCSSRuleSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_PRECREATE)
 
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager,
                                        nsMessageManagerSH<nsEventTargetSH>,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS |
                                        nsIXPCScriptable::WANT_ENUMERATE |
@@ -508,21 +492,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DOMConstructor, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(CSSMediaRule, nsIDOMCSSMediaRule)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMediaRule)
-  DOM_CLASSINFO_MAP_END
-
 #ifdef MOZ_XUL
   DOM_CLASSINFO_MAP_BEGIN(XULCommandDispatcher, nsIDOMXULCommandDispatcher)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandDispatcher)
   DOM_CLASSINFO_MAP_END
 #endif
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULControllers, nsIControllers)
     DOM_CLASSINFO_MAP_ENTRY(nsIControllers)
@@ -546,26 +525,16 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(XULTreeBuilder, nsIXULTreeBuilder)
     DOM_CLASSINFO_MAP_ENTRY(nsIXULTreeBuilder)
     DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder)
     DOM_CLASSINFO_MAP_ENTRY(nsITreeView)
   DOM_CLASSINFO_MAP_END
 #endif
 
-  DOM_CLASSINFO_MAP_BEGIN(CSSMozDocumentRule, nsIDOMCSSMozDocumentRule)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(CSSSupportsRule, nsIDOMCSSSupportsRule)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSSupportsRule)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(CSSFontFaceRule, nsIDOMCSSFontFaceRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFaceRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsISupports)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
--- a/dom/base/nsDOMClassInfoID.h
+++ b/dom/base/nsDOMClassInfoID.h
@@ -14,37 +14,31 @@
 
 #include "nsIXPCScriptable.h"
 
 enum nsDOMClassInfoID
 {
   eDOMClassInfo_DOMPrototype_id,
   eDOMClassInfo_DOMConstructor_id,
 
-  // CSS classes
-  eDOMClassInfo_CSSMediaRule_id,
-
   // XUL classes
 #ifdef MOZ_XUL
   eDOMClassInfo_XULCommandDispatcher_id,
 #endif
   eDOMClassInfo_XULControllers_id,
 #ifdef MOZ_XUL
   eDOMClassInfo_TreeSelection_id,
   eDOMClassInfo_TreeContentView_id,
 #endif
 
 #ifdef MOZ_XUL
   eDOMClassInfo_XULTemplateBuilder_id,
   eDOMClassInfo_XULTreeBuilder_id,
 #endif
 
-  eDOMClassInfo_CSSMozDocumentRule_id,
-  eDOMClassInfo_CSSSupportsRule_id,
-
   // @font-face in CSS
   eDOMClassInfo_CSSFontFaceRule_id,
 
   eDOMClassInfo_ContentFrameMessageManager_id,
   eDOMClassInfo_ContentProcessMessageManager_id,
   eDOMClassInfo_ChromeMessageBroadcaster_id,
   eDOMClassInfo_ChromeMessageSender_id,
 
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -14,21 +14,16 @@
 #include "js/RootingAPI.h"
 #include "js/TracingAPI.h"
 
 namespace mozilla {
 namespace dom {
 class TabChildGlobal;
 class ProcessGlobal;
 } // namespace dom
-namespace css {
-class MediaRule;
-class DocumentRule;
-} // namespace css
-class CSSSupportsRule;
 } // namespace mozilla
 class SandboxPrivate;
 class nsInProcessTabChildGlobal;
 class nsWindowRoot;
 class nsCSSFontFaceRule;
 class nsCSSFontFeatureValuesRule;
 class nsCSSKeyframeRule;
 class nsCSSKeyframesRule;
@@ -286,19 +281,16 @@ private:
   // Friend declarations for things that need to be able to call
   // SetIsNotDOMBinding().  The goal is to get rid of all of these, and
   // SetIsNotDOMBinding() too.
   friend class mozilla::dom::TabChildGlobal;
   friend class mozilla::dom::ProcessGlobal;
   friend class SandboxPrivate;
   friend class nsInProcessTabChildGlobal;
   friend class nsWindowRoot;
-  friend class mozilla::css::MediaRule;
-  friend class mozilla::css::DocumentRule;
-  friend class mozilla::CSSSupportsRule;
   friend class nsCSSFontFaceRule;
   friend class nsCSSFontFeatureValuesRule;
   friend class nsCSSKeyframeRule;
   friend class nsCSSKeyframesRule;
   friend class nsCSSPageRule;
   friend class nsCSSCounterStyleRule;
   void SetIsNotDOMBinding()
   {
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -191,24 +191,45 @@ DOMInterfaces = {
 'CSS': {
     'concrete': False,
 },
 
 'CSS2Properties': {
     'nativeType': 'nsDOMCSSDeclaration'
 },
 
+'CSSConditionRule': {
+    'concrete': False,
+    'nativeType': 'mozilla::css::ConditionRule',
+    'headerFile': 'mozilla/css/GroupRule.h',
+},
+
+'CSSGroupingRule': {
+    'concrete': False,
+    'nativeType': 'mozilla::css::GroupRule',
+},
+
 'CSSImportRule': {
     'nativeType': 'mozilla::css::ImportRule',
 },
 
 'CSSLexer': {
     'wrapperCache': False
 },
 
+'CSSMediaRule': {
+    'nativeType': 'mozilla::css::MediaRule',
+    'headerFile': 'nsCSSRules.h',
+},
+
+'CSSMozDocumentRule': {
+    'nativeType': 'mozilla::css::DocumentRule',
+    'headerFile': 'nsCSSRules.h',
+},
+
 'CSSNamespaceRule': {
     'nativeType': 'mozilla::css::NameSpaceRule',
 },
 
 'CSSPrimitiveValue': {
     'nativeType': 'nsROCSSPrimitiveValue',
 },
 
@@ -226,16 +247,21 @@ DOMInterfaces = {
     'nativeType': 'mozilla::BindingStyleRule',
 },
 
 'CSSStyleSheet': {
     'nativeType': 'mozilla::StyleSheet',
     'binaryNames': { 'ownerRule': 'DOMOwnerRule' },
 },
 
+'CSSSupportsRule': {
+    'nativeType': 'mozilla::CSSSupportsRule',
+    'headerFile': 'nsCSSRules.h',
+},
+
 'CSSValue': {
     'concrete': False
 },
 
 'CSSValueList': {
     'nativeType': 'nsDOMCSSValueList'
 },
 
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSConditionRule.webidl
@@ -0,0 +1,14 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * https://drafts.csswg.org/css-conditional/#the-cssconditionrule-interface
+ */
+
+// https://drafts.csswg.org/css-conditional/#the-cssconditionrule-interface
+interface CSSConditionRule : CSSGroupingRule {
+  [SetterThrows]
+  attribute DOMString conditionText;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSGroupingRule.webidl
@@ -0,0 +1,17 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * https://drafts.csswg.org/cssom/#cssgroupingrule
+ */
+
+// https://drafts.csswg.org/cssom/#cssgroupingrule
+interface CSSGroupingRule : CSSRule {
+  [SameObject] readonly attribute CSSRuleList cssRules;
+  [Throws]
+  unsigned long insertRule(DOMString rule, unsigned long index);
+  [Throws]
+  void deleteRule(unsigned long index);
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSMediaRule.webidl
@@ -0,0 +1,17 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * https://drafts.csswg.org/cssom/#the-cssmediarule-interface
+ * https://drafts.csswg.org/css-conditional/#the-cssmediarule-interface
+ */
+
+// https://drafts.csswg.org/cssom/#the-cssmediarule-interface and
+// https://drafts.csswg.org/css-conditional/#the-cssmediarule-interface
+// except they disagree with each other.  We're taking the inheritance from
+// css-conditional and the PutForwards behavior from cssom.
+interface CSSMediaRule : CSSConditionRule {
+  [SameObject, PutForwards=mediaText] readonly attribute MediaList media;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSMozDocumentRule.webidl
@@ -0,0 +1,10 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ */
+
+// This is a non-standard interface for @-moz-document rules
+interface CSSMozDocumentRule : CSSConditionRule {
+  // XXX Add access to the URL list.
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSSupportsRule.webidl
@@ -0,0 +1,12 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * https://drafts.csswg.org/css-conditional/#the-csssupportsrule-interface
+ */
+
+// https://drafts.csswg.org/css-conditional/#the-csssupportsrule-interface
+interface CSSSupportsRule : CSSConditionRule {
+};
--- a/dom/webidl/LegacyQueryInterface.webidl
+++ b/dom/webidl/LegacyQueryInterface.webidl
@@ -19,16 +19,17 @@ interface LegacyQueryInterface {
 };
 
 Attr implements LegacyQueryInterface;
 BarProp implements LegacyQueryInterface;
 BoxObject implements LegacyQueryInterface;
 CaretPosition implements LegacyQueryInterface;
 Comment implements LegacyQueryInterface;
 Crypto implements LegacyQueryInterface;
+CSSMozDocumentRule implements LegacyQueryInterface;
 CSSPrimitiveValue implements LegacyQueryInterface;
 CSSStyleDeclaration implements LegacyQueryInterface;
 CSSStyleRule implements LegacyQueryInterface;
 CSSValueList implements LegacyQueryInterface;
 DOMImplementation implements LegacyQueryInterface;
 DOMParser implements LegacyQueryInterface;
 DOMStringMap implements LegacyQueryInterface;
 DOMTokenList implements LegacyQueryInterface;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -84,26 +84,31 @@ WEBIDL_FILES = [
     'ConvolverNode.webidl',
     'Coordinates.webidl',
     'CreateOfferRequest.webidl',
     'Crypto.webidl',
     'CSPDictionaries.webidl',
     'CSPReport.webidl',
     'CSS.webidl',
     'CSSAnimation.webidl',
+    'CSSConditionRule.webidl',
+    'CSSGroupingRule.webidl',
     'CSSImportRule.webidl',
     'CSSLexer.webidl',
+    'CSSMediaRule.webidl',
+    'CSSMozDocumentRule.webidl',
     'CSSNamespaceRule.webidl',
     'CSSPrimitiveValue.webidl',
     'CSSPseudoElement.webidl',
     'CSSRule.webidl',
     'CSSRuleList.webidl',
     'CSSStyleDeclaration.webidl',
     'CSSStyleRule.webidl',
     'CSSStyleSheet.webidl',
+    'CSSSupportsRule.webidl',
     'CSSTransition.webidl',
     'CSSValue.webidl',
     'CSSValueList.webidl',
     'CustomElementRegistry.webidl',
     'DataContainerEvent.webidl',
     'DataTransfer.webidl',
     'DataTransferItem.webidl',
     'DataTransferItemList.webidl',
--- a/layout/style/GroupRule.h
+++ b/layout/style/GroupRule.h
@@ -7,28 +7,33 @@
  * internal interface representing CSS style rules that contain other
  * rules, such as @media rules
  */
 
 #ifndef mozilla_css_GroupRule_h__
 #define mozilla_css_GroupRule_h__
 
 #include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
 #include "mozilla/IncrementalClearCOMRuleArray.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/css/Rule.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsPresContext;
 class nsMediaQueryResultCacheKey;
 
 namespace mozilla {
 
 class StyleSheet;
 
+namespace dom {
+class CSSRuleList;
+} // namespace dom
+
 namespace css {
 
 class GroupRuleRuleList;
 
 // inherits from Rule so it can be shared between
 // MediaRule and DocumentRule
 class GroupRule : public Rule
 {
@@ -74,27 +79,51 @@ public:
   static bool
   CloneRuleInto(Rule* aRule, void* aArray)
   {
     RefPtr<Rule> clone = aRule->Clone();
     static_cast<IncrementalClearCOMRuleArray*>(aArray)->AppendObject(clone);
     return true;
   }
 
+  // WebIDL API
+  dom::CSSRuleList* CssRules();
+  uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
+                      ErrorResult& aRv);
+  void DeleteRule(uint32_t aIndex, ErrorResult& aRv);
+
 protected:
   // to help implement nsIDOMCSSRule
   void AppendRulesToCssText(nsAString& aCssText) const;
 
   // to implement common methods on nsIDOMCSSMediaRule and
   // nsIDOMCSSMozDocumentRule
   nsresult GetCssRules(nsIDOMCSSRuleList* *aRuleList);
   nsresult InsertRule(const nsAString & aRule, uint32_t aIndex,
                       uint32_t* _retval);
   nsresult DeleteRule(uint32_t aIndex);
 
   IncrementalClearCOMRuleArray mRules;
   RefPtr<GroupRuleRuleList> mRuleCollection; // lazily constructed
 };
 
+// Implementation of WebIDL CSSConditionRule.
+class ConditionRule : public GroupRule
+{
+protected:
+  ConditionRule(uint32_t aLineNumber, uint32_t aColumnNumber);
+  ConditionRule(const ConditionRule& aCopy);
+  virtual ~ConditionRule();
+
+public:
+
+  // GetConditionText signature matches nsIDOMCSSConditionRule, so subclasses
+  // can implement this easily.  The implementations should never return
+  // anything other than NS_OK.
+  NS_IMETHOD GetConditionText(nsAString& aConditionText) = 0;
+  virtual void SetConditionText(const nsAString& aConditionText,
+                                ErrorResult& aRv) = 0;
+};
+
 } // namespace css
 } // namespace mozilla
 
 #endif /* mozilla_css_GroupRule_h__ */
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -30,16 +30,19 @@
 #include "nsError.h"
 #include "nsStyleUtil.h"
 #include "mozilla/DeclarationBlockInlines.h"
 #include "nsCSSParser.h"
 #include "nsDOMClassInfoID.h"
 #include "mozilla/dom/CSSStyleDeclarationBinding.h"
 #include "mozilla/dom/CSSNamespaceRuleBinding.h"
 #include "mozilla/dom/CSSImportRuleBinding.h"
+#include "mozilla/dom/CSSMediaRuleBinding.h"
+#include "mozilla/dom/CSSSupportsRuleBinding.h"
+#include "mozilla/dom/CSSMozDocumentRuleBinding.h"
 #include "StyleRule.h"
 #include "nsFont.h"
 #include "nsIURI.h"
 #include "mozAutoDocUpdate.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
@@ -606,108 +609,160 @@ GroupRule::AppendRulesToCssText(nsAStrin
 
   aCssText.Append('}');
 }
 
 // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
 nsresult
 GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
 {
+  NS_ADDREF(*aRuleList = CssRules());
+  return NS_OK;
+}
+
+CSSRuleList*
+GroupRule::CssRules()
+{
   if (!mRuleCollection) {
     mRuleCollection = new css::GroupRuleRuleList(this);
   }
 
-  NS_ADDREF(*aRuleList = mRuleCollection);
-  return NS_OK;
+  return mRuleCollection;
 }
 
 nsresult
 GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
 {
+  ErrorResult rv;
+  *_retval = InsertRule(aRule, aIndex, rv);
+  return rv.StealNSResult();
+}
+
+uint32_t
+GroupRule::InsertRule(const nsAString& aRule, uint32_t aIndex, ErrorResult& aRv)
+{
   StyleSheet* sheet = GetStyleSheet();
-  NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
-  
-  if (aIndex > uint32_t(mRules.Count()))
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  if (NS_WARN_IF(!sheet)) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return 0;
+  }
+
+  if (aIndex > uint32_t(mRules.Count())) {
+    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    return 0;
+  }
 
   NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
                "Too many style rules!");
 
-  return sheet->AsGecko()->InsertRuleIntoGroup(aRule, this, aIndex, _retval);
+  uint32_t retval;
+  nsresult rv =
+    sheet->AsGecko()->InsertRuleIntoGroup(aRule, this, aIndex, &retval);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return 0;
+  }
+  return retval;
 }
 
 nsresult
 GroupRule::DeleteRule(uint32_t aIndex)
 {
+  ErrorResult rv;
+  DeleteRule(aIndex, rv);
+  return rv.StealNSResult();
+}
+
+void
+GroupRule::DeleteRule(uint32_t aIndex, ErrorResult& aRv)
+{
   StyleSheet* sheet = GetStyleSheet();
-  NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
-
-  if (aIndex >= uint32_t(mRules.Count()))
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  if (NS_WARN_IF(!sheet)) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  if (aIndex >= uint32_t(mRules.Count())) {
+    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    return;
+  }
 
   NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
                "Too many style rules!");
 
-  return sheet->AsGecko()->DeleteRuleFromGroup(this, aIndex);
+  nsresult rv = sheet->AsGecko()->DeleteRuleFromGroup(this, aIndex);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
 }
 
 /* virtual */ size_t
 GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
   for (size_t i = 0; i < mRules.Length(); i++) {
     n += mRules[i]->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mRuleCollection
   return n;
 }
 
+ConditionRule::ConditionRule(uint32_t aLineNumber, uint32_t aColumnNumber)
+  : GroupRule(aLineNumber, aColumnNumber)
+{
+}
+
+ConditionRule::ConditionRule(const ConditionRule& aCopy)
+  : GroupRule(aCopy)
+{
+}
+
+ConditionRule::~ConditionRule()
+{
+}
 
 // -------------------------------------------
 // nsICSSMediaRule
 //
 MediaRule::MediaRule(uint32_t aLineNumber, uint32_t aColumnNumber)
-  : GroupRule(aLineNumber, aColumnNumber)
+  : ConditionRule(aLineNumber, aColumnNumber)
 {
-  SetIsNotDOMBinding();
 }
 
 MediaRule::MediaRule(const MediaRule& aCopy)
-  : GroupRule(aCopy)
+  : ConditionRule(aCopy)
 {
-  SetIsNotDOMBinding();
   if (aCopy.mMedia) {
     mMedia = aCopy.mMedia->Clone();
     // XXXldb This doesn't really make sense.
     mMedia->SetStyleSheet(aCopy.GetStyleSheet());
   }
 }
 
 MediaRule::~MediaRule()
 {
   if (mMedia) {
     mMedia->SetStyleSheet(nullptr);
   }
 }
 
-NS_IMPL_ADDREF_INHERITED(MediaRule, GroupRule)
-NS_IMPL_RELEASE_INHERITED(MediaRule, GroupRule)
+NS_IMPL_ADDREF_INHERITED(MediaRule, ConditionRule)
+NS_IMPL_RELEASE_INHERITED(MediaRule, ConditionRule)
 
 // QueryInterface implementation for MediaRule
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMediaRule)
-NS_INTERFACE_MAP_END_INHERITING(GroupRule)
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRule, GroupRule,
+NS_INTERFACE_MAP_END_INHERITING(ConditionRule)
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRule, ConditionRule,
                                    mMedia)
 
 /* virtual */ void
 MediaRule::SetStyleSheet(StyleSheet* aSheet)
 {
   if (mMedia) {
     // Set to null so it knows it's leaving one sheet and joining another.
     mMedia->SetStyleSheet(nullptr);
@@ -769,16 +824,24 @@ MediaRule::SetMedia(nsMediaList* aMedia)
 }
 
 uint16_t
 MediaRule::Type() const
 {
   return nsIDOMCSSRule::MEDIA_RULE;
 }
 
+nsMediaList*
+MediaRule::Media() const
+{
+  // In practice, if we end up being parsed at all, we have non-null mMedia.  So
+  // it's OK to claim we don't return null here.
+  return mMedia;
+}
+
 void
 MediaRule::GetCssTextImpl(nsAString& aCssText) const
 {
   aCssText.AssignLiteral("@media ");
   AppendConditionText(aCssText);
   GroupRule::AppendRulesToCssText(aCssText);
 }
 
@@ -808,27 +871,41 @@ MediaRule::GetConditionText(nsAString& a
   aConditionText.Truncate(0);
   AppendConditionText(aConditionText);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MediaRule::SetConditionText(const nsAString& aConditionText)
 {
+  ErrorResult rv;
+  SetConditionText(aConditionText, rv);
+  return rv.StealNSResult();
+}
+
+void
+MediaRule::SetConditionText(const nsAString& aConditionText,
+                            ErrorResult& aRv)
+{
   if (!mMedia) {
     RefPtr<nsMediaList> media = new nsMediaList();
     media->SetStyleSheet(GetStyleSheet());
     nsresult rv = media->SetMediaText(aConditionText);
     if (NS_SUCCEEDED(rv)) {
       mMedia = media;
+    } else {
+      aRv.Throw(rv);
     }
-    return rv;
+    return;
   }
 
-  return mMedia->SetMediaText(aConditionText);
+  nsresult rv = mMedia->SetMediaText(aConditionText);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
 }
 
 // nsIDOMCSSMediaRule methods
 NS_IMETHODIMP
 MediaRule::GetMedia(nsIDOMMediaList* *aMedia)
 {
   NS_ENSURE_ARG_POINTER(aMedia);
   NS_IF_ADDREF(*aMedia = mMedia);
@@ -858,57 +935,53 @@ MediaRule::SizeOfIncludingThis(MallocSiz
 
   return n;
 }
 
 /* virtual */ JSObject*
 MediaRule::WrapObject(JSContext* aCx,
                       JS::Handle<JSObject*> aGivenProto)
 {
-  NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
-  return nullptr;
+  return CSSMediaRuleBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 MediaRule::AppendConditionText(nsAString& aOutput) const
 {
   if (mMedia) {
     nsAutoString mediaText;
     mMedia->GetText(mediaText);
     aOutput.Append(mediaText);
   }
 }
 
 DocumentRule::DocumentRule(uint32_t aLineNumber, uint32_t aColumnNumber)
-  : GroupRule(aLineNumber, aColumnNumber)
+  : ConditionRule(aLineNumber, aColumnNumber)
 {
-  SetIsNotDOMBinding();
 }
 
 DocumentRule::DocumentRule(const DocumentRule& aCopy)
-  : GroupRule(aCopy)
+  : ConditionRule(aCopy)
   , mURLs(new URL(*aCopy.mURLs))
 {
-  SetIsNotDOMBinding();
 }
 
 DocumentRule::~DocumentRule()
 {
 }
 
-NS_IMPL_ADDREF_INHERITED(DocumentRule, GroupRule)
-NS_IMPL_RELEASE_INHERITED(DocumentRule, GroupRule)
+NS_IMPL_ADDREF_INHERITED(DocumentRule, ConditionRule)
+NS_IMPL_RELEASE_INHERITED(DocumentRule, ConditionRule)
 
 // QueryInterface implementation for DocumentRule
 NS_INTERFACE_MAP_BEGIN(DocumentRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMozDocumentRule)
-NS_INTERFACE_MAP_END_INHERITING(GroupRule)
+NS_INTERFACE_MAP_END_INHERITING(ConditionRule)
 
 #ifdef DEBUG
 /* virtual */ void
 DocumentRule::List(FILE* out, int32_t aIndent) const
 {
   nsAutoCString indentStr;
   for (int32_t indent = aIndent; --indent >= 0; ) {
     indentStr.AppendLiteral("  ");
@@ -1002,16 +1075,23 @@ DocumentRule::GetConditionText(nsAString
 }
 
 NS_IMETHODIMP
 DocumentRule::SetConditionText(const nsAString& aConditionText)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+void
+DocumentRule::SetConditionText(const nsAString& aConditionText,
+                               ErrorResult& aRv)
+{
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+}
+
 // GroupRule interface
 /* virtual */ bool
 DocumentRule::UseForPresentation(nsPresContext* aPresContext,
                                  nsMediaQueryResultCacheKey& aKey)
 {
   return UseForPresentation(aPresContext);
 }
 
@@ -1081,18 +1161,17 @@ DocumentRule::SizeOfIncludingThis(Malloc
 
   return n;
 }
 
 /* virtual */ JSObject*
 DocumentRule::WrapObject(JSContext* aCx,
                          JS::Handle<JSObject*> aGivenProto)
 {
-  NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
-  return nullptr;
+  return CSSMozDocumentRuleBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 DocumentRule::AppendConditionText(nsAString& aCssText) const
 {
   for (URL *url = mURLs; url; url = url->next) {
     switch (url->func) {
       case eURL:
@@ -2628,33 +2707,31 @@ nsCSSPageRule::WrapObject(JSContext* aCx
   return nullptr;
 }
 
 namespace mozilla {
 
 CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
                                  const nsString& aCondition,
                                  uint32_t aLineNumber, uint32_t aColumnNumber)
-  : css::GroupRule(aLineNumber, aColumnNumber)
+  : css::ConditionRule(aLineNumber, aColumnNumber)
   , mUseGroup(aConditionMet)
   , mCondition(aCondition)
 {
-  SetIsNotDOMBinding();
 }
 
 CSSSupportsRule::~CSSSupportsRule()
 {
 }
 
 CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy)
-  : css::GroupRule(aCopy),
+  : css::ConditionRule(aCopy),
     mUseGroup(aCopy.mUseGroup),
     mCondition(aCopy.mCondition)
 {
-  SetIsNotDOMBinding();
 }
 
 #ifdef DEBUG
 /* virtual */ void
 CSSSupportsRule::List(FILE* out, int32_t aIndent) const
 {
   nsAutoCString indentStr;
   for (int32_t indent = aIndent; --indent >= 0; ) {
@@ -2685,26 +2762,25 @@ CSSSupportsRule::Clone() const
 
 /* virtual */ bool
 CSSSupportsRule::UseForPresentation(nsPresContext* aPresContext,
                                    nsMediaQueryResultCacheKey& aKey)
 {
   return mUseGroup;
 }
 
-NS_IMPL_ADDREF_INHERITED(CSSSupportsRule, css::GroupRule)
-NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::GroupRule)
+NS_IMPL_ADDREF_INHERITED(CSSSupportsRule, css::ConditionRule)
+NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::ConditionRule)
 
 // QueryInterface implementation for CSSSupportsRule
 NS_INTERFACE_MAP_BEGIN(CSSSupportsRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSSupportsRule)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSSupportsRule)
-NS_INTERFACE_MAP_END_INHERITING(GroupRule)
+NS_INTERFACE_MAP_END_INHERITING(ConditionRule)
 
 uint16_t
 CSSSupportsRule::Type() const
 {
   return nsIDOMCSSRule::SUPPORTS_RULE;
 }
 
 void
@@ -2743,31 +2819,37 @@ CSSSupportsRule::GetConditionText(nsAStr
 }
 
 NS_IMETHODIMP
 CSSSupportsRule::SetConditionText(const nsAString& aConditionText)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+void
+CSSSupportsRule::SetConditionText(const nsAString& aConditionText,
+                                  ErrorResult& aRv)
+{
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+}
+
 /* virtual */ size_t
 CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
   n += css::GroupRule::SizeOfExcludingThis(aMallocSizeOf);
   n += mCondition.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
   return n;
 }
 
 /* virtual */ JSObject*
 CSSSupportsRule::WrapObject(JSContext* aCx,
                             JS::Handle<JSObject*> aGivenProto)
 {
-  NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
-  return nullptr;
+  return CSSSupportsRuleBinding::Wrap(aCx, this, aGivenProto);
 }
 
 } // namespace mozilla
 
 // -------------------------------------------
 // nsCSSCounterStyleRule
 //
 
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -38,27 +38,27 @@
 class nsMediaList;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace css {
 
-class MediaRule final : public GroupRule,
+class MediaRule final : public ConditionRule,
                         public nsIDOMCSSMediaRule
 {
 public:
   MediaRule(uint32_t aLineNumber, uint32_t aColumnNumber);
 private:
   MediaRule(const MediaRule& aCopy);
   ~MediaRule();
 public:
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaRule, GroupRule)
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaRule, ConditionRule)
   NS_DECL_ISUPPORTS_INHERITED
 
   // Rule methods
 #ifdef DEBUG
   virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
 #endif
   virtual void SetStyleSheet(mozilla::StyleSheet* aSheet) override; //override GroupRule
   mozilla::CSSStyleSheet* GetStyleSheet() const
@@ -84,30 +84,34 @@ public:
                                     nsMediaQueryResultCacheKey& aKey) override;
 
   // @media rule methods
   nsresult SetMedia(nsMediaList* aMedia);
 
   // WebIDL interface
   uint16_t Type() const override;
   void GetCssTextImpl(nsAString& aCssText) const override;
+  // Our XPCOM GetConditionText is OK
+  virtual void SetConditionText(const nsAString& aConditionText,
+                                ErrorResult& aRv) override;
+  nsMediaList* Media() const;
   
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     const override MOZ_MUST_OVERRIDE;
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
 protected:
   void AppendConditionText(nsAString& aOutput) const;
 
   RefPtr<nsMediaList> mMedia;
 };
 
-class DocumentRule final : public GroupRule,
+class DocumentRule final : public ConditionRule,
                            public nsIDOMCSSMozDocumentRule
 {
 public:
   DocumentRule(uint32_t aLineNumber, uint32_t aColumnNumber);
 private:
   DocumentRule(const DocumentRule& aCopy);
   ~DocumentRule();
 public:
@@ -159,16 +163,19 @@ public:
     ~URL();
   };
 
   void SetURLs(URL *aURLs) { mURLs = aURLs; }
 
   // WebIDL interface
   uint16_t Type() const override;
   void GetCssTextImpl(nsAString& aCssText) const override;
+  // Our XPCOM GetConditionText is OK
+  virtual void SetConditionText(const nsAString& aConditionText,
+                                ErrorResult& aRv) override;
 
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     const override MOZ_MUST_OVERRIDE;
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
 protected:
@@ -576,17 +583,17 @@ public:
 private:
   RefPtr<mozilla::css::Declaration>     mDeclaration;
   // lazily created when needed:
   RefPtr<nsCSSPageStyleDeclaration>     mDOMDeclaration;
 };
 
 namespace mozilla {
 
-class CSSSupportsRule final : public css::GroupRule,
+class CSSSupportsRule final : public css::ConditionRule,
                               public nsIDOMCSSSupportsRule
 {
 public:
   CSSSupportsRule(bool aConditionMet, const nsString& aCondition,
                   uint32_t aLineNumber, uint32_t aColumnNumber);
   CSSSupportsRule(const CSSSupportsRule& aCopy);
 
   // Rule methods
@@ -608,16 +615,19 @@ public:
   NS_DECL_NSIDOMCSSCONDITIONRULE
 
   // nsIDOMCSSSupportsRule interface
   NS_DECL_NSIDOMCSSSUPPORTSRULE
 
   // WebIDL interface
   uint16_t Type() const override;
   void GetCssTextImpl(nsAString& aCssText) const override;
+  // Our XPCOM GetConditionText is OK
+  virtual void SetConditionText(const nsAString& aConditionText,
+                                ErrorResult& aRv) override;
 
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
 protected:
   virtual ~CSSSupportsRule();