Bug 846972 part 2. Add the WebIDL APIs for StyleSheet and CSSStyleSheet. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Sun, 17 Mar 2013 10:42:59 -0400
changeset 125141 883db473ec469f8377ba4922776673a21b5e8dc6
parent 125140 946419184f9983a5ccd945cee78f0bbcaa6749d8
child 125142 dd888bc71adc649891a1ab6bfa3d2d10b73d1d82
push id24449
push useremorley@mozilla.com
push dateMon, 18 Mar 2013 20:06:48 +0000
treeherdermozilla-central@e23e43a2c14e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs846972
milestone22.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 846972 part 2. Add the WebIDL APIs for StyleSheet and CSSStyleSheet. r=peterv
content/base/public/nsIStyleSheetLinkingElement.h
content/base/src/nsStyleLinkElement.cpp
content/base/src/nsStyleLinkElement.h
content/html/content/src/HTMLLinkElement.cpp
content/html/content/src/HTMLLinkElement.h
content/html/content/src/HTMLStyleElement.cpp
content/html/content/src/HTMLStyleElement.h
dom/bindings/BindingDeclarations.h
dom/bindings/BindingUtils.h
dom/interfaces/html/nsIDOMHTMLLinkElement.idl
dom/interfaces/html/nsIDOMHTMLStyleElement.idl
dom/webidl/CSSStyleSheet.webidl
dom/webidl/HTMLLinkElement.webidl
dom/webidl/HTMLStyleElement.webidl
dom/webidl/StyleSheet.webidl
layout/style/Loader.cpp
layout/style/nsCSSStyleSheet.cpp
layout/style/nsCSSStyleSheet.h
--- a/content/base/public/nsIStyleSheetLinkingElement.h
+++ b/content/base/public/nsIStyleSheetLinkingElement.h
@@ -11,29 +11,30 @@
 class nsICSSLoaderObserver;
 class nsIURI;
 
 #define NS_ISTYLESHEETLINKINGELEMENT_IID          \
 { 0xd753c84a, 0x17fd, 0x4d5f, \
  { 0xb2, 0xe9, 0x63, 0x52, 0x8c, 0x87, 0x99, 0x7a } }
 
 class nsIStyleSheet;
+class nsCSSStyleSheet;
 
 class nsIStyleSheetLinkingElement : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISTYLESHEETLINKINGELEMENT_IID)
 
   /**
    * Used to make the association between a style sheet and
    * the element that linked it to the document.
    *
    * @param aStyleSheet the style sheet associated with this
    *                    element.
    */
-  NS_IMETHOD SetStyleSheet(nsIStyleSheet* aStyleSheet) = 0;
+  NS_IMETHOD SetStyleSheet(nsCSSStyleSheet* aStyleSheet) = 0;
 
   /**
    * Used to obtain the style sheet linked in by this element.
    *
    * @param aStyleSheet out parameter that returns the style
    *                    sheet associated with this element.
    */
   NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aStyleSheet) = 0;
--- a/content/base/src/nsStyleLinkElement.cpp
+++ b/content/base/src/nsStyleLinkElement.cpp
@@ -51,31 +51,27 @@ nsStyleLinkElement::Unlink()
 void
 nsStyleLinkElement::Traverse(nsCycleCollectionTraversalCallback &cb)
 {
   nsStyleLinkElement* tmp = this;
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheet);
 }
 
 NS_IMETHODIMP 
-nsStyleLinkElement::SetStyleSheet(nsIStyleSheet* aStyleSheet)
+nsStyleLinkElement::SetStyleSheet(nsCSSStyleSheet* aStyleSheet)
 {
-  nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(mStyleSheet);
-  if (cssSheet) {
-    cssSheet->SetOwningNode(nullptr);
+  if (mStyleSheet) {
+    mStyleSheet->SetOwningNode(nullptr);
   }
 
   mStyleSheet = aStyleSheet;
-  cssSheet = do_QueryObject(mStyleSheet);
-  if (cssSheet) {
-    nsCOMPtr<nsIDOMNode> node;
-    CallQueryInterface(this,
-                       static_cast<nsIDOMNode**>(getter_AddRefs(node)));
+  if (mStyleSheet) {
+    nsCOMPtr<nsINode> node = do_QueryObject(this);
     if (node) {
-      cssSheet->SetOwningNode(node);
+      mStyleSheet->SetOwningNode(node);
     }
   }
     
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsStyleLinkElement::GetStyleSheet(nsIStyleSheet*& aStyleSheet)
@@ -92,25 +88,17 @@ nsStyleLinkElement::InitStyleLinkElement
   mDontLoadStyle = aDontLoadStyle;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStyleLinkElement::GetSheet(nsIDOMStyleSheet** aSheet)
 {
-  NS_ENSURE_ARG_POINTER(aSheet);
-  *aSheet = nullptr;
-
-  if (mStyleSheet) {
-    CallQueryInterface(mStyleSheet, aSheet);
-  }
-
-  // Always return NS_OK to avoid throwing JS exceptions if mStyleSheet 
-  // is not a nsIDOMStyleSheet
+  NS_IF_ADDREF(*aSheet = mStyleSheet);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStyleLinkElement::SetEnableUpdates(bool aEnableUpdates)
 {
   mUpdatesEnabled = aEnableUpdates;
 
@@ -411,38 +399,34 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
 
 void
 nsStyleLinkElement::UpdateStyleSheetScopedness(bool aIsNowScoped)
 {
   if (!mStyleSheet) {
     return;
   }
 
-  nsRefPtr<nsCSSStyleSheet> cssStyleSheet = do_QueryObject(mStyleSheet);
-  NS_ASSERTION(cssStyleSheet, "should only call UpdateStyleSheetScope for "
-                              "an nsCSSStyleSheet");
-
   nsCOMPtr<nsIContent> thisContent;
   CallQueryInterface(this, getter_AddRefs(thisContent));
 
-  Element* oldScopeElement = cssStyleSheet->GetScopeElement();
+  Element* oldScopeElement = mStyleSheet->GetScopeElement();
   Element* newScopeElement = aIsNowScoped ?
                                thisContent->GetParentElement() :
                                nullptr;
 
   if (oldScopeElement == newScopeElement) {
     return;
   }
 
   nsIDocument* document = thisContent->GetOwnerDocument();
 
   document->BeginUpdate(UPDATE_STYLE);
   document->RemoveStyleSheet(mStyleSheet);
 
-  cssStyleSheet->SetScopeElement(newScopeElement);
+  mStyleSheet->SetScopeElement(newScopeElement);
 
   document->AddStyleSheet(mStyleSheet);
   document->EndUpdate(UPDATE_STYLE);
 
   if (oldScopeElement) {
     UpdateIsElementInStyleScopeFlagOnSubtree(oldScopeElement);
   }
   if (newScopeElement) {
--- a/content/base/src/nsStyleLinkElement.h
+++ b/content/base/src/nsStyleLinkElement.h
@@ -11,17 +11,17 @@
  */
 
 #ifndef nsStyleLinkElement_h___
 #define nsStyleLinkElement_h___
 
 #include "nsCOMPtr.h"
 #include "nsIDOMLinkStyle.h"
 #include "nsIStyleSheetLinkingElement.h"
-#include "nsIStyleSheet.h"
+#include "nsCSSStyleSheet.h"
 #include "nsIURI.h"
 #include "nsTArray.h"
 #include "mozilla/CORSMode.h"
 
 #define PREFETCH      0x00000001
 #define DNS_PREFETCH  0x00000002
 #define STYLESHEET    0x00000004
 #define NEXT          0x00000008
@@ -36,20 +36,20 @@ public:
   nsStyleLinkElement();
   virtual ~nsStyleLinkElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0;
 
   // nsIDOMLinkStyle
   NS_DECL_NSIDOMLINKSTYLE
 
-  nsIStyleSheet* GetSheet() { return mStyleSheet; }
+  nsCSSStyleSheet* GetSheet() const { return mStyleSheet; }
 
   // nsIStyleSheetLinkingElement  
-  NS_IMETHOD SetStyleSheet(nsIStyleSheet* aStyleSheet);
+  NS_IMETHOD SetStyleSheet(nsCSSStyleSheet* aStyleSheet);
   NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aStyleSheet);
   NS_IMETHOD InitStyleLinkElement(bool aDontLoadStyle);
   NS_IMETHOD UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
                               bool* aWillNotify,
                               bool* aIsAlternate);
   NS_IMETHOD SetEnableUpdates(bool aEnableUpdates);
   NS_IMETHOD GetCharset(nsAString& aCharset);
 
@@ -100,17 +100,17 @@ private:
    *                     changed but the URI may not have changed.
    */
   nsresult DoUpdateStyleSheet(nsIDocument *aOldDocument,
                               nsICSSLoaderObserver* aObserver,
                               bool* aWillNotify,
                               bool* aIsAlternate,
                               bool aForceUpdate);
 
-  nsCOMPtr<nsIStyleSheet> mStyleSheet;
+  nsRefPtr<nsCSSStyleSheet> mStyleSheet;
 protected:
   bool mDontLoadStyle;
   bool mUpdatesEnabled;
   uint32_t mLineNumber;
 };
 
 #endif /* nsStyleLinkElement_h___ */
 
--- a/content/html/content/src/HTMLLinkElement.cpp
+++ b/content/html/content/src/HTMLLinkElement.cpp
@@ -64,53 +64,44 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLLinkElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLLinkElement)
 
 bool
-HTMLLinkElement::GetDisabled(ErrorResult& aRv)
+HTMLLinkElement::Disabled()
 {
-  nsCOMPtr<nsIDOMStyleSheet> ss = do_QueryInterface(GetSheet());
-  if (!ss) {
-    return false;
-  }
-
-  bool disabled = false;
-  aRv = ss->GetDisabled(&disabled);
-  return disabled;
+  nsCSSStyleSheet* ss = GetSheet();
+  return ss && ss->Disabled();
 }
 
 NS_IMETHODIMP
-HTMLLinkElement::GetDisabled(bool* aDisabled)
+HTMLLinkElement::GetMozDisabled(bool* aDisabled)
 {
-  ErrorResult rv;
-  *aDisabled = GetDisabled(rv);
-  return rv.ErrorCode();
+  *aDisabled = Disabled();
+  return NS_OK;
 }
 
 void
-HTMLLinkElement::SetDisabled(bool aDisabled, ErrorResult& aRv)
+HTMLLinkElement::SetDisabled(bool aDisabled)
 {
-  nsCOMPtr<nsIDOMStyleSheet> ss = do_QueryInterface(GetSheet());
-  if (!ss) {
-    return;
+  nsCSSStyleSheet* ss = GetSheet();
+  if (ss) {
+    ss->SetDisabled(aDisabled);
   }
 
-  aRv = ss->SetDisabled(aDisabled);
 }
 
 NS_IMETHODIMP
-HTMLLinkElement::SetDisabled(bool aDisabled)
+HTMLLinkElement::SetMozDisabled(bool aDisabled)
 {
-  ErrorResult rv;
-  SetDisabled(aDisabled, rv);
-  return rv.ErrorCode();
+  SetDisabled(aDisabled);
+  return NS_OK;
 }
 
 
 NS_IMPL_STRING_ATTR(HTMLLinkElement, Charset, charset)
 NS_IMPL_URI_ATTR(HTMLLinkElement, Href, href)
 NS_IMPL_STRING_ATTR(HTMLLinkElement, Hreflang, hreflang)
 NS_IMPL_STRING_ATTR(HTMLLinkElement, Media, media)
 NS_IMPL_STRING_ATTR(HTMLLinkElement, Rel, rel)
--- a/content/html/content/src/HTMLLinkElement.h
+++ b/content/html/content/src/HTMLLinkElement.h
@@ -87,18 +87,18 @@ public:
                               const nsAString& aValue,
                               nsAttrValue& aResult);
   virtual void GetLinkTarget(nsAString& aTarget);
   virtual nsEventStates IntrinsicState() const;
 
   void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
 
   // WebIDL
-  bool GetDisabled(ErrorResult& aRv);
-  void SetDisabled(bool aDisabled, ErrorResult& aRv);
+  bool Disabled();
+  void SetDisabled(bool aDisabled);
   // XPCOM GetHref is fine.
   void SetHref(const nsAString& aHref, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::href, aHref, aRv);
   }
   // XPCOM GetCrossOrigin is fine.
   void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aRv)
   {
--- a/content/html/content/src/HTMLStyleElement.cpp
+++ b/content/html/content/src/HTMLStyleElement.cpp
@@ -56,57 +56,44 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLStyleElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLStyleElement)
 
 
 NS_IMETHODIMP
-HTMLStyleElement::GetDisabled(bool* aDisabled)
+HTMLStyleElement::GetMozDisabled(bool* aDisabled)
 {
   NS_ENSURE_ARG_POINTER(aDisabled);
 
   *aDisabled = Disabled();
   return NS_OK;
 }
 
 bool
 HTMLStyleElement::Disabled()
 {
-  nsCOMPtr<nsIDOMStyleSheet> ss = do_QueryInterface(GetSheet());
-  if (!ss) {
-    return false;
-  }
-
-  bool disabled = false;
-  ss->GetDisabled(&disabled);
-
-  return disabled;
+  nsCSSStyleSheet* ss = GetSheet();
+  return ss && ss->Disabled();
 }
 
 NS_IMETHODIMP
-HTMLStyleElement::SetDisabled(bool aDisabled)
+HTMLStyleElement::SetMozDisabled(bool aDisabled)
 {
-  ErrorResult error;
-  SetDisabled(aDisabled, error);
-  return error.ErrorCode();
+  SetDisabled(aDisabled);
+  return NS_OK;
 }
 
 void
-HTMLStyleElement::SetDisabled(bool aDisabled, ErrorResult& aError)
+HTMLStyleElement::SetDisabled(bool aDisabled)
 {
-  nsCOMPtr<nsIDOMStyleSheet> ss = do_QueryInterface(GetSheet());
-  if (!ss) {
-    return;
-  }
-
-  nsresult result = ss->SetDisabled(aDisabled);
-  if (NS_FAILED(result)) {
-    aError.Throw(result);
+  nsCSSStyleSheet* ss = GetSheet();
+  if (ss) {
+    ss->SetDisabled(aDisabled);
   }
 }
 
 NS_IMPL_STRING_ATTR(HTMLStyleElement, Media, media)
 NS_IMPL_BOOL_ATTR(HTMLStyleElement, Scoped, scoped)
 NS_IMPL_STRING_ATTR(HTMLStyleElement, Type, type)
 
 void
--- a/content/html/content/src/HTMLStyleElement.h
+++ b/content/html/content/src/HTMLStyleElement.h
@@ -69,17 +69,17 @@ public:
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   bool Disabled();
-  void SetDisabled(bool aDisabled, ErrorResult& aError);
+  void SetDisabled(bool aDisabled);
   void SetMedia(const nsAString& aMedia, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::media, aMedia, aError);
   }
   void SetType(const nsAString& aType, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::type, aType, aError);
   }
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -16,16 +16,22 @@
 #include "nsStringGlue.h"
 #include "jsapi.h"
 #include "mozilla/Util.h"
 #include "nsCOMPtr.h"
 #include "nsDOMString.h"
 #include "nsStringBuffer.h"
 #include "nsTArray.h"
 
+class nsWrapperCache;
+
+// nsGlobalWindow implements nsWrapperCache, but doesn't always use it. Don't
+// try to use it without fixing that first.
+class nsGlobalWindow;
+
 namespace mozilla {
 namespace dom {
 
 struct MainThreadDictionaryBase
 {
 protected:
   JSContext* ParseJSON(const nsAString& aJSON,
                        mozilla::Maybe<JSAutoRequest>& aAr,
@@ -374,12 +380,58 @@ private:
   // Don't allow copy-construction of these objects, because it'll do the wrong
   // thing with our flag mCx.
   RootedJSValue(const RootedJSValue&) MOZ_DELETE;
 
   JS::Value mValue;
   JSContext* mCx;
 };
 
+inline nsWrapperCache*
+GetWrapperCache(nsWrapperCache* cache)
+{
+  return cache;
+}
+
+inline nsWrapperCache*
+GetWrapperCache(nsGlobalWindow* not_allowed);
+
+inline nsWrapperCache*
+GetWrapperCache(void* p)
+{
+  return NULL;
+}
+
+// Helper template for smart pointers to resolve ambiguity between
+// GetWrappeCache(void*) and GetWrapperCache(const ParentObject&).
+template <template <typename> class SmartPtr, typename T>
+inline nsWrapperCache*
+GetWrapperCache(const SmartPtr<T>& aObject)
+{
+  return GetWrapperCache(aObject.get());
+}
+
+struct ParentObject {
+  template<class T>
+  ParentObject(T* aObject) :
+    mObject(aObject),
+    mWrapperCache(GetWrapperCache(aObject))
+  {}
+
+  template<class T, template<typename> class SmartPtr>
+  ParentObject(const SmartPtr<T>& aObject) :
+    mObject(aObject.get()),
+    mWrapperCache(GetWrapperCache(aObject.get()))
+  {}
+
+  ParentObject(nsISupports* aObject, nsWrapperCache* aCache) :
+    mObject(aObject),
+    mWrapperCache(aCache)
+  {}
+
+  nsISupports* const mObject;
+  nsWrapperCache* const mWrapperCache;
+};
+
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_BindingDeclarations_h__
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -20,20 +20,16 @@
 #include "qsObjectHelper.h"
 #include "xpcpublic.h"
 #include "nsTraceRefcnt.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/Likely.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/CallbackObject.h"
 
-// nsGlobalWindow implements nsWrapperCache, but doesn't always use it. Don't
-// try to use it without fixing that first.
-class nsGlobalWindow;
-
 namespace mozilla {
 namespace dom {
 
 bool
 ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...);
 
 template<bool mainThread>
 inline bool
@@ -677,40 +673,16 @@ WrapNewBindingNonWrapperCachedObject(JSC
 bool
 NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx,
                                          JSObject* aScope,
                                          JS::Value* aRetval,
                                          xpcObjectHelper& aHelper,
                                          const nsIID* aIID,
                                          bool aAllowNativeWrapper);
 
-inline nsWrapperCache*
-GetWrapperCache(nsWrapperCache* cache)
-{
-  return cache;
-}
-
-inline nsWrapperCache*
-GetWrapperCache(nsGlobalWindow* not_allowed);
-
-inline nsWrapperCache*
-GetWrapperCache(void* p)
-{
-  return NULL;
-}
-
-// Helper template for smart pointers to resolve ambiguity between
-// GetWrappeCache(void*) and GetWrapperCache(const ParentObject&).
-template <template <typename> class SmartPtr, typename T>
-inline nsWrapperCache*
-GetWrapperCache(const SmartPtr<T>& aObject)
-{
-  return GetWrapperCache(aObject.get());
-}
-
 /**
  * A method to handle new-binding wrap failure, by possibly falling back to
  * wrapping as a non-new-binding object.
  */
 template <class T>
 MOZ_ALWAYS_INLINE bool
 HandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope, T* value,
                                 JS::Value* vp)
@@ -822,38 +794,16 @@ FindEnumStringIndex(JSContext* cx, JS::V
       return i;
     }
   }
 
   *ok = EnumValueNotFound<InvalidValueFatal>(cx, chars, length, type);
   return -1;
 }
 
-struct ParentObject {
-  template<class T>
-  ParentObject(T* aObject) :
-    mObject(aObject),
-    mWrapperCache(GetWrapperCache(aObject))
-  {}
-
-  template<class T, template<typename> class SmartPtr>
-  ParentObject(const SmartPtr<T>& aObject) :
-    mObject(aObject.get()),
-    mWrapperCache(GetWrapperCache(aObject.get()))
-  {}
-
-  ParentObject(nsISupports* aObject, nsWrapperCache* aCache) :
-    mObject(aObject),
-    mWrapperCache(aCache)
-  {}
-
-  nsISupports* const mObject;
-  nsWrapperCache* const mWrapperCache;
-};
-
 inline nsWrapperCache*
 GetWrapperCache(const ParentObject& aParentObject)
 {
   return aParentObject.mWrapperCache;
 }
 
 template<class T>
 inline T*
--- a/dom/interfaces/html/nsIDOMHTMLLinkElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLLinkElement.idl
@@ -14,16 +14,17 @@
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
 [scriptable, uuid(ca856a0b-6786-4123-90fe-dc9c7600274e)]
 interface nsIDOMHTMLLinkElement : nsIDOMHTMLElement
 {
+           [binaryname(MozDisabled)]
            attribute boolean          disabled;
            attribute DOMString        charset;
            attribute DOMString        href;
            attribute DOMString        hreflang;
            attribute DOMString        media;
            attribute DOMString        rel;
            attribute DOMString        rev;
            attribute DOMString        target;
--- a/dom/interfaces/html/nsIDOMHTMLStyleElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLStyleElement.idl
@@ -14,13 +14,14 @@
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
 [scriptable, uuid(5e6c9cac-5594-4006-ae3f-ad82fb28cee9)]
 interface nsIDOMHTMLStyleElement : nsIDOMHTMLElement
 {
+           [binaryname(MozDisabled)]
            attribute boolean          disabled;
            attribute DOMString        media;
            attribute DOMString        type;
            attribute boolean          scoped;
 };
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSStyleSheet.webidl
@@ -0,0 +1,22 @@
+/* -*- 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
+ * http://dev.w3.org/csswg/cssom/
+ */
+
+interface CSSRuleList;
+interface CSSRule;
+
+interface CSSStyleSheet : StyleSheet {
+  [Pure]
+  readonly attribute CSSRule? ownerRule;
+  [Throws]
+  readonly attribute CSSRuleList cssRules;
+  [Throws]
+  unsigned long insertRule(DOMString rule, unsigned long index);
+  [Throws]
+  void deleteRule(unsigned long index);
+};
--- a/dom/webidl/HTMLLinkElement.webidl
+++ b/dom/webidl/HTMLLinkElement.webidl
@@ -8,17 +8,17 @@
  * http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 // http://www.whatwg.org/specs/web-apps/current-work/#the-link-element
 interface HTMLLinkElement : HTMLElement {
-  [Throws]
+  [Pure]
            attribute boolean disabled;
   [SetterThrows, Pure]
            attribute DOMString href;
   [SetterThrows, Pure]
            attribute DOMString crossOrigin;
   [SetterThrows, Pure]
            attribute DOMString rel;
 // Not supported yet:
--- a/dom/webidl/HTMLStyleElement.webidl
+++ b/dom/webidl/HTMLStyleElement.webidl
@@ -4,19 +4,19 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  * http://www.whatwg.org/specs/web-apps/current-work/#the-style-element
  * http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
  */
 
 interface HTMLStyleElement : HTMLElement {
-           [SetterThrows]
+           [Pure]
            attribute boolean disabled;
-           [SetterThrows]
+           [SetterThrows, Pure]
            attribute DOMString media;
-           [SetterThrows]
+           [SetterThrows, Pure]
            attribute DOMString type;
-           [SetterThrows]
+           [SetterThrows, Pure]
            attribute boolean scoped;
 };
 HTMLStyleElement implements LinkStyle;
 
new file mode 100644
--- /dev/null
+++ b/dom/webidl/StyleSheet.webidl
@@ -0,0 +1,30 @@
+/* -*- 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
+ * http://dev.w3.org/csswg/cssom/
+ */
+
+interface CSSRule;
+interface MediaList;
+
+interface StyleSheet {
+  [Constant]
+  readonly attribute DOMString type;
+  [Constant]
+  readonly attribute DOMString? href;
+  // Spec says "Node", but it can go null when the node gets a new
+  // sheet.  That's also why it's not [Constant]
+  [Pure]
+  readonly attribute Node? ownerNode;
+  [Pure]
+  readonly attribute StyleSheet? parentStyleSheet;
+  [Pure]
+  readonly attribute DOMString? title;
+  [Constant]
+  readonly attribute MediaList media;
+  [Pure]
+  attribute boolean disabled;
+};
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -2419,17 +2419,17 @@ CountSheetMemory(URIPrincipalAndCORSMode
                  const nsRefPtr<nsCSSStyleSheet>& aSheet,
                  nsMallocSizeOfFun aMallocSizeOf,
                  void* /* unused */)
 {
   // If aSheet has a parent, then its parent will report it so we don't
   // have to worry about it here.
   // Likewise, if aSheet has an owning node, then the document that
   // node is in will report it.
-  if (aSheet->GetOwningNode() || aSheet->GetParentSheet()) {
+  if (aSheet->GetOwnerNode() || aSheet->GetParentSheet()) {
     return 0;
   }
   return aSheet->SizeOfIncludingThis(aMallocSizeOf);
 }
 
 size_t
 Loader::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -549,22 +549,17 @@ nsMediaList::GetText(nsAString& aMediaTe
 
 // XXXbz this is so ill-defined in the spec, it's not clear quite what
 // it should be doing....
 nsresult
 nsMediaList::SetText(const nsAString& aMediaText)
 {
   nsCSSParser parser;
 
-  bool htmlMode = false;
-  if (mStyleSheet) {
-    nsCOMPtr<nsIDOMNode> node;
-    mStyleSheet->GetOwnerNode(getter_AddRefs(node));
-    htmlMode = !!node;
-  }
+  bool htmlMode = mStyleSheet && mStyleSheet->GetOwnerNode();
 
   return parser.ParseMediaList(aMediaText, nullptr, 0,
                                this, htmlMode);
 }
 
 bool
 nsMediaList::Matches(nsPresContext* aPresContext,
                      nsMediaQueryResultCacheKey* aKey)
@@ -1039,17 +1034,17 @@ nsCSSStyleSheet::nsCSSStyleSheet(CORSMod
 
   mInner = new nsCSSStyleSheetInner(this, aCORSMode);
 }
 
 nsCSSStyleSheet::nsCSSStyleSheet(const nsCSSStyleSheet& aCopy,
                                  nsCSSStyleSheet* aParentToUse,
                                  css::ImportRule* aOwnerRuleToUse,
                                  nsIDocument* aDocumentToUse,
-                                 nsIDOMNode* aOwningNodeToUse)
+                                 nsINode* aOwningNodeToUse)
   : mTitle(aCopy.mTitle),
     mParent(aParentToUse),
     mOwnerRule(aOwnerRuleToUse),
     mDocument(aDocumentToUse),
     mOwningNode(aOwningNodeToUse),
     mDisabled(aCopy.mDisabled),
     mDirty(aCopy.mDirty),
     mScopeElement(nullptr),
@@ -1378,18 +1373,17 @@ uint64_t
 nsCSSStyleSheet::FindOwningWindowInnerID() const
 {
   uint64_t windowID = 0;
   if (mDocument) {
     windowID = mDocument->InnerWindowID();
   }
 
   if (windowID == 0 && mOwningNode) {
-    nsCOMPtr<nsINode> node = do_QueryInterface(mOwningNode);
-    windowID = node->OwnerDoc()->InnerWindowID();
+    windowID = mOwningNode->OwnerDoc()->InnerWindowID();
   }
 
   if (windowID == 0 && mOwnerRule) {
     nsCOMPtr<nsIStyleSheet> sheet = static_cast<css::Rule*>(mOwnerRule)->GetStyleSheet();
     if (sheet) {
       nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(sheet);
       if (cssSheet) {
         windowID = cssSheet->FindOwningWindowInnerID();
@@ -1577,17 +1571,17 @@ nsCSSStyleSheet::AppendAllChildSheets(ns
   }
   return true;
 }
 
 already_AddRefed<nsCSSStyleSheet>
 nsCSSStyleSheet::Clone(nsCSSStyleSheet* aCloneParent,
                        css::ImportRule* aCloneOwnerRule,
                        nsIDocument* aCloneDocument,
-                       nsIDOMNode* aCloneOwningNode) const
+                       nsINode* aCloneOwningNode) const
 {
   nsCSSStyleSheet* clone = new nsCSSStyleSheet(*this,
                                                aCloneParent,
                                                aCloneOwnerRule,
                                                aCloneDocument,
                                                aCloneOwningNode);
   NS_IF_ADDREF(clone);
   return clone;
@@ -1752,34 +1746,34 @@ nsCSSStyleSheet::GetType(nsAString& aTyp
 {
   aType.AssignLiteral("text/css");
   return NS_OK;
 }
 
 NS_IMETHODIMP    
 nsCSSStyleSheet::GetDisabled(bool* aDisabled)
 {
-  *aDisabled = mDisabled;
+  *aDisabled = Disabled();
   return NS_OK;
 }
 
 NS_IMETHODIMP    
 nsCSSStyleSheet::SetDisabled(bool aDisabled)
 {
   // DOM method, so handle BeginUpdate/EndUpdate
   MOZ_AUTO_DOC_UPDATE(mDocument, UPDATE_STYLE, true);
   nsCSSStyleSheet::SetEnabled(!aDisabled);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCSSStyleSheet::GetOwnerNode(nsIDOMNode** aOwnerNode)
 {
-  *aOwnerNode = mOwningNode;
-  NS_IF_ADDREF(*aOwnerNode);
+  nsCOMPtr<nsIDOMNode> ownerNode = do_QueryInterface(GetOwnerNode());
+  ownerNode.forget(aOwnerNode);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCSSStyleSheet::GetParentStyleSheet(nsIDOMStyleSheet** aParentStyleSheet)
 {
   NS_ENSURE_ARG_POINTER(aParentStyleSheet);
 
@@ -1813,63 +1807,76 @@ nsCSSStyleSheet::GetTitle(nsAString& aTi
 {
   aTitle.Assign(mTitle);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCSSStyleSheet::GetMedia(nsIDOMMediaList** aMedia)
 {
-  NS_ENSURE_ARG_POINTER(aMedia);
-  *aMedia = nullptr;
+  NS_ADDREF(*aMedia = Media());
+  return NS_OK;
+}
 
+nsIDOMMediaList*
+nsCSSStyleSheet::Media()
+{
   if (!mMedia) {
     mMedia = new nsMediaList();
-    NS_ENSURE_TRUE(mMedia, NS_ERROR_OUT_OF_MEMORY);
     mMedia->SetStyleSheet(this);
   }
 
-  *aMedia = mMedia;
-  NS_ADDREF(*aMedia);
-
-  return NS_OK;
+  return mMedia;
 }
 
 NS_IMETHODIMP    
 nsCSSStyleSheet::GetOwnerRule(nsIDOMCSSRule** aOwnerRule)
 {
-  if (mOwnerRule) {
-    NS_IF_ADDREF(*aOwnerRule = mOwnerRule->GetDOMRule());
-  } else {
-    *aOwnerRule = nullptr;
-  }
+  NS_IF_ADDREF(*aOwnerRule = GetOwnerRule());
   return NS_OK;
 }
 
+nsIDOMCSSRule*
+nsCSSStyleSheet::GetDOMOwnerRule() const
+{
+  return mOwnerRule ? mOwnerRule->GetDOMRule() : nullptr;
+}
+
 NS_IMETHODIMP    
 nsCSSStyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules)
 {
+  ErrorResult rv;
+  nsCOMPtr<nsIDOMCSSRuleList> rules = GetCssRules(rv);
+  rules.forget(aCssRules);
+  return rv.ErrorCode();
+}
+
+nsIDOMCSSRuleList*
+nsCSSStyleSheet::GetCssRules(ErrorResult& aRv)
+{
   // No doing this on incomplete sheets!
   if (!mInner->mComplete) {
-    return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+    return nullptr;
   }
   
   //-- Security check: Only scripts whose principal subsumes that of the
   //   style sheet can access rule collections.
   nsresult rv = SubjectSubsumesInnerPrincipal();
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return nullptr;
+  }
 
   // OK, security check passed, so get the rule collection
-  if (nullptr == mRuleCollection) {
+  if (!mRuleCollection) {
     mRuleCollection = new CSSRuleListImpl(this);
   }
 
-  NS_ADDREF(*aCssRules = mRuleCollection);
-
-  return NS_OK;
+  return mRuleCollection;
 }
 
 NS_IMETHODIMP    
 nsCSSStyleSheet::InsertRule(const nsAString& aRule, 
                             uint32_t aIndex, 
                             uint32_t* aReturn)
 {
   //-- Security check: Only scripts whose principal subsumes that of the
--- a/layout/style/nsCSSStyleSheet.h
+++ b/layout/style/nsCSSStyleSheet.h
@@ -171,28 +171,27 @@ public:
   // Principal() never returns a null pointer.
   nsIPrincipal* Principal() const { return mInner->mPrincipal; }
 
   // The document this style sheet is associated with.  May be null
   nsIDocument* GetDocument() const { return mDocument; }
 
   void SetTitle(const nsAString& aTitle) { mTitle = aTitle; }
   void SetMedia(nsMediaList* aMedia);
-  void SetOwningNode(nsIDOMNode* aOwningNode) { mOwningNode = aOwningNode; /* Not ref counted */ }
-  nsIDOMNode* GetOwningNode() const { return mOwningNode; }
+  void SetOwningNode(nsINode* aOwningNode) { mOwningNode = aOwningNode; /* Not ref counted */ }
 
   void SetOwnerRule(mozilla::css::ImportRule* aOwnerRule) { mOwnerRule = aOwnerRule; /* Not ref counted */ }
   mozilla::css::ImportRule* GetOwnerRule() const { return mOwnerRule; }
 
   nsXMLNameSpaceMap* GetNameSpaceMap() const { return mInner->mNameSpaceMap; }
 
   already_AddRefed<nsCSSStyleSheet> Clone(nsCSSStyleSheet* aCloneParent,
                                           mozilla::css::ImportRule* aCloneOwnerRule,
                                           nsIDocument* aCloneDocument,
-                                          nsIDOMNode* aCloneOwningNode) const;
+                                          nsINode* aCloneOwningNode) const;
 
   bool IsModified() const { return mDirty; }
 
   void SetModifiedByChildRule() {
     NS_ASSERTION(mDirty,
                  "sheet must be marked dirty before handing out child rules");
     DidDirty();
   }
@@ -250,22 +249,66 @@ public:
   mozilla::CORSMode GetCORSMode() const { return mInner->mCORSMode; }
 
   mozilla::dom::Element* GetScopeElement() const { return mScopeElement; }
   void SetScopeElement(mozilla::dom::Element* aScopeElement)
   {
     mScopeElement = aScopeElement;
   }
 
+  // WebIDL StyleSheet API
+  // Our nsIStyleSheet::GetType is a const method, so it ends up
+  // ambiguous with with the XPCOM version.  Just disambiguate.
+  void GetType(nsString& aType) {
+    const_cast<const nsCSSStyleSheet*>(this)->GetType(aType);
+  }
+  // Our XPCOM GetHref is fine for WebIDL
+  nsINode* GetOwnerNode() const { return mOwningNode; }
+  nsCSSStyleSheet* GetParentStyleSheet() const { return mParent; }
+  // Our nsIStyleSheet::GetTitle is a const method, so it ends up
+  // ambiguous with with the XPCOM version.  Just disambiguate.
+  void GetTitle(nsString& aTitle) {
+    const_cast<const nsCSSStyleSheet*>(this)->GetTitle(aTitle);
+  }
+  nsIDOMMediaList* Media();
+  bool Disabled() const { return mDisabled; }
+  // The XPCOM SetDisabled is fine for WebIDL
+
+  // WebIDL CSSStyleSheet API
+  // Can't be inline because we can't include ImportRule here.  And can't be
+  // called GetOwnerRule because that would be ambiguous with the ImportRule
+  // version.
+  nsIDOMCSSRule* GetDOMOwnerRule() const;
+  nsIDOMCSSRuleList* GetCssRules(mozilla::ErrorResult& aRv);
+  uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
+                      mozilla::ErrorResult& aRv) {
+    uint32_t retval;
+    aRv = InsertRule(aRule, aIndex, &retval);
+    return retval;
+  }
+  void DeleteRule(uint32_t aIndex, mozilla::ErrorResult& aRv) {
+    aRv = DeleteRule(aIndex);
+  }
+
+  // WebIDL miscellaneous bits
+  mozilla::dom::ParentObject GetParentObject() const {
+    if (mOwningNode) {
+      return mozilla::dom::ParentObject(mOwningNode);
+    }
+
+    return mozilla::dom::ParentObject(static_cast<nsIStyleSheet*>(mParent),
+                                      mParent);
+  }
+
 private:
   nsCSSStyleSheet(const nsCSSStyleSheet& aCopy,
                   nsCSSStyleSheet* aParentToUse,
                   mozilla::css::ImportRule* aOwnerRuleToUse,
                   nsIDocument* aDocumentToUse,
-                  nsIDOMNode* aOwningNodeToUse);
+                  nsINode* aOwningNodeToUse);
 
   nsCSSStyleSheet(const nsCSSStyleSheet& aCopy) MOZ_DELETE;
   nsCSSStyleSheet& operator=(const nsCSSStyleSheet& aCopy) MOZ_DELETE;
 
 protected:
   virtual ~nsCSSStyleSheet();
 
   void ClearRuleCascades();
@@ -297,17 +340,17 @@ protected:
   nsString              mTitle;
   nsRefPtr<nsMediaList> mMedia;
   nsRefPtr<nsCSSStyleSheet> mNext;
   nsCSSStyleSheet*      mParent;    // weak ref
   mozilla::css::ImportRule* mOwnerRule; // weak ref
 
   nsRefPtr<CSSRuleListImpl> mRuleCollection;
   nsIDocument*          mDocument; // weak ref; parents maintain this for their children
-  nsIDOMNode*           mOwningNode; // weak ref
+  nsINode*              mOwningNode; // weak ref
   bool                  mDisabled;
   bool                  mDirty; // has been modified 
   nsRefPtr<mozilla::dom::Element> mScopeElement;
 
   nsCSSStyleSheetInner* mInner;
 
   nsAutoTArray<nsCSSRuleProcessor*, 8>* mRuleProcessors;