Bug 1459498: Use StyleSheetInfo more. r?heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sun, 06 May 2018 16:10:09 +0200
changeset 791902 56b67e492d5788d1d841f73a19b66c790f20e8be
parent 791901 b2e875d2eb1d6e5ccb747a97e1082017f97cc1d2
child 791903 f23ca27993eeedd820d1450b738cb8009e73c3f8
push id108915
push userbmo:emilio@crisal.io
push dateSun, 06 May 2018 14:46:32 +0000
reviewersheycam
bugs1459498
milestone61.0a1
Bug 1459498: Use StyleSheetInfo more. r?heycam Not as much as I'd like, because we have all the internal loads and child sheets, but... MozReview-Commit-ID: 7402w8vxCel
dom/base/nsContentSink.cpp
dom/base/nsIStyleSheetLinkingElement.h
dom/base/nsStyleLinkElement.cpp
dom/base/nsStyleLinkElement.h
layout/style/Loader.cpp
layout/style/Loader.h
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -51,16 +51,17 @@
 #include "mozilla/dom/ServiceWorkerDescriptor.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "nsParserConstants.h"
 #include "nsSandboxFlags.h"
 #include "Link.h"
 #include "HTMLLinkElement.h"
 
 using namespace mozilla;
+using namespace mozilla::css;
 using namespace mozilla::dom;
 
 LazyLogModule gContentSinkLogModuleInfo("nscontentsink");
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsContentSink)
@@ -778,28 +779,34 @@ nsContentSink::ProcessStyleLinkFromHeade
   nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr,
                           mDocument->GetDocBaseURI());
 
   if (NS_FAILED(rv)) {
     // The URI is bad, move along, don't propagate the error (for now)
     return NS_OK;
   }
 
-  mozilla::net::ReferrerPolicy referrerPolicy =
-    mozilla::net::AttributeReferrerPolicyFromString(aReferrerPolicy);
-  if (referrerPolicy == net::RP_Unset) {
-    referrerPolicy = mDocument->GetReferrerPolicy();
-  }
+
+  Loader::StyleSheetInfo info {
+    *mDocument,
+    nullptr,
+    url.forget(),
+    nullptr,
+    net::AttributeReferrerPolicyFromString(aReferrerPolicy),
+    CORS_NONE,
+    aTitle,
+    aMedia,
+    aAlternate ? Loader::HasAlternateRel::Yes : Loader::HasAlternateRel::No,
+    Loader::IsInline::No,
+  };
+
   // If this is a fragment parser, we don't want to observe.
   // We don't support CORS for processing instructions
   auto loadResultOrErr =
-    mCSSLoader->LoadStyleLink(nullptr, url, nullptr, aTitle, aMedia, aAlternate,
-                              CORS_NONE, referrerPolicy,
-                              /* integrity = */ EmptyString(),
-                              mRunsToCompletion ? nullptr : this);
+    mCSSLoader->LoadStyleLink(info, mRunsToCompletion ? nullptr : this);
   if (loadResultOrErr.isErr()) {
     return loadResultOrErr.unwrapErr();
   }
 
   if (loadResultOrErr.unwrap().ShouldBlock() && !mRunsToCompletion) {
     ++mPendingSheetCount;
     mScriptLoader->AddParserBlockingScriptExecutionBlocker();
   }
--- a/dom/base/nsIStyleSheetLinkingElement.h
+++ b/dom/base/nsIStyleSheetLinkingElement.h
@@ -6,41 +6,55 @@
 #ifndef nsIStyleSheetLinkingElement_h__
 #define nsIStyleSheetLinkingElement_h__
 
 
 #include "nsISupports.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/Result.h"
 
+class nsIContent;
 class nsICSSLoaderObserver;
+class nsIPrincipal;
 class nsIURI;
 
 #define NS_ISTYLESHEETLINKINGELEMENT_IID          \
 { 0xa8b79f3b, 0x9d18, 0x4f9c, \
   { 0xb1, 0xaa, 0x8c, 0x9b, 0x1b, 0xaa, 0xac, 0xad } }
 
 class nsIStyleSheetLinkingElement : public nsISupports {
 public:
   enum class ForceUpdate
   {
     Yes,
     No,
   };
 
+  enum class Completed
+  {
+    Yes,
+    No,
+  };
+
+  enum class HasAlternateRel
+  {
+    Yes,
+    No
+  };
+
   enum class IsAlternate
   {
     Yes,
     No,
   };
 
-  enum class Completed
+  enum class IsInline
   {
     Yes,
-    No,
+    No
   };
 
   enum class MediaMatched
   {
     Yes,
     No,
   };
 
@@ -74,16 +88,47 @@ public:
       if (!mWillNotify) {
         return false;
       }
 
       return !mIsAlternate && mMediaMatched;
     }
   };
 
+  struct MOZ_STACK_CLASS StyleSheetInfo
+  {
+    nsIContent* mContent;
+    // FIXME(emilio): do these really need to be strong refs?
+    nsCOMPtr<nsIURI> mURI;
+    nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
+    mozilla::net::ReferrerPolicy mReferrerPolicy;
+    mozilla::CORSMode mCORSMode;
+    nsAutoString mTitle;
+    nsAutoString mMedia;
+    nsAutoString mIntegrity;
+
+    bool mIsAlternate : 1;
+    bool mHasAlternateRel : 1;
+    bool mIsInline : 1;
+
+    StyleSheetInfo(const nsIDocument&,
+                   nsIContent*,
+                   already_AddRefed<nsIURI> aURI,
+                   already_AddRefed<nsIPrincipal> aTriggeringPrincipal,
+                   mozilla::net::ReferrerPolicy aReferrerPolicy,
+                   mozilla::CORSMode aCORSMode,
+                   const nsAString& aTitle,
+                   const nsAString& aMedia,
+                   HasAlternateRel aHasAlternateRel,
+                   IsInline aIsInline);
+
+    ~StyleSheetInfo();
+  };
+
+
   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.
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -32,27 +32,28 @@
 #include "nsStyleUtil.h"
 #include "nsQueryObject.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsStyleLinkElement::StyleSheetInfo::StyleSheetInfo(
   const nsIDocument& aDocument,
-  const nsIContent* aContent,
+  nsIContent* aContent,
   already_AddRefed<nsIURI> aURI,
   already_AddRefed<nsIPrincipal> aTriggeringPrincipal,
   mozilla::net::ReferrerPolicy aReferrerPolicy,
   mozilla::CORSMode aCORSMode,
   const nsAString& aTitle,
   const nsAString& aMedia,
   HasAlternateRel aHasAlternateRel,
   IsInline aIsInline
 )
-  : mURI(aURI)
+  : mContent(aContent)
+  , mURI(aURI)
   , mTriggeringPrincipal(aTriggeringPrincipal)
   , mReferrerPolicy(aReferrerPolicy)
   , mCORSMode(aCORSMode)
   , mTitle(aTitle)
   , mMedia(aMedia)
   , mHasAlternateRel(aHasAlternateRel == HasAlternateRel::Yes)
   , mIsInline(aIsInline == IsInline::Yes)
 {
@@ -355,47 +356,29 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
                                            mLineNumber, text, &rv)) {
       if (NS_FAILED(rv)) {
         return Err(rv);
       }
       return Update { };
     }
 
     // Parse the style sheet.
-    return doc->CSSLoader()->
-      LoadInlineStyle(thisContent,
-                      text,
-                      info->mTriggeringPrincipal,
-                      mLineNumber,
-                      info->mTitle,
-                      info->mMedia,
-                      info->mReferrerPolicy,
-                      aObserver);
+    return doc->CSSLoader()->LoadInlineStyle(*info, text, mLineNumber, aObserver);
   }
   nsAutoString integrity;
   if (thisContent->IsElement()) {
     thisContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::integrity,
                                       integrity);
   }
   if (!integrity.IsEmpty()) {
     MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
             ("nsStyleLinkElement::DoUpdateStyleSheet, integrity=%s",
              NS_ConvertUTF16toUTF8(integrity).get()));
   }
-  auto resultOrError =
-    doc->CSSLoader()->LoadStyleLink(thisContent,
-                                    info->mURI,
-                                    info->mTriggeringPrincipal,
-                                    info->mTitle,
-                                    info->mMedia,
-                                    info->mHasAlternateRel,
-                                    info->mCORSMode,
-                                    info->mReferrerPolicy,
-                                    info->mIntegrity,
-                                    aObserver);
+  auto resultOrError = doc->CSSLoader()->LoadStyleLink(*info, aObserver);
   if (resultOrError.isErr()) {
     // Don't propagate LoadStyleLink() errors further than this, since some
     // consumers (e.g. nsXMLContentSink) will completely abort on innocuous
     // things like a stylesheet load being blocked by the security system.
     return Update { };
   }
   return resultOrError;
 }
--- a/dom/base/nsStyleLinkElement.h
+++ b/dom/base/nsStyleLinkElement.h
@@ -29,59 +29,16 @@ namespace mozilla {
 class CSSStyleSheet;
 namespace dom {
 class ShadowRoot;
 } // namespace dom
 } // namespace mozilla
 
 class nsStyleLinkElement : public nsIStyleSheetLinkingElement
 {
-protected:
-  enum class IsInline
-  {
-    Yes,
-    No
-  };
-
-  enum class HasAlternateRel
-  {
-    Yes,
-    No
-  };
-
-  struct MOZ_STACK_CLASS StyleSheetInfo
-  {
-    const nsIContent* mContent;
-    // FIXME(emilio): do these really need to be strong refs?
-    nsCOMPtr<nsIURI> mURI;
-    nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
-    mozilla::net::ReferrerPolicy mReferrerPolicy;
-    mozilla::CORSMode mCORSMode;
-    nsAutoString mTitle;
-    nsAutoString mMedia;
-    nsAutoString mIntegrity;
-
-    bool mIsAlternate : 1;
-    bool mHasAlternateRel : 1;
-    bool mIsInline : 1;
-
-    StyleSheetInfo(const nsIDocument&,
-                   const nsIContent*,
-                   already_AddRefed<nsIURI> aURI,
-                   already_AddRefed<nsIPrincipal> aTriggeringPrincipal,
-                   mozilla::net::ReferrerPolicy aReferrerPolicy,
-                   mozilla::CORSMode aCORSMode,
-                   const nsAString& aTitle,
-                   const nsAString& aMedia,
-                   HasAlternateRel aHasAlternateRel,
-                   IsInline aIsInline);
-
-    ~StyleSheetInfo();
-  };
-
 public:
   nsStyleLinkElement();
   virtual ~nsStyleLinkElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override = 0;
 
   mozilla::StyleSheet* GetSheet() const { return mStyleSheet; }
 
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1880,87 +1880,91 @@ Loader::MarkLoadTreeFailed(SheetLoadData
       MarkLoadTreeFailed(aLoadData->mParentData);
     }
 
     aLoadData = aLoadData->mNext;
   } while (aLoadData);
 }
 
 Result<Loader::LoadSheetResult, nsresult>
-Loader::LoadInlineStyle(nsIContent* aElement,
+Loader::LoadInlineStyle(const StyleSheetInfo& aInfo,
                         const nsAString& aBuffer,
-                        nsIPrincipal* aTriggeringPrincipal,
                         uint32_t aLineNumber,
-                        const nsAString& aTitle,
-                        const nsAString& aMedia,
-                        ReferrerPolicy aReferrerPolicy,
                         nsICSSLoaderObserver* aObserver)
 {
   LOG(("css::Loader::LoadInlineStyle"));
 
   if (!mEnabled) {
     LOG_WARN(("  Not enabled"));
     return Err(NS_ERROR_NOT_AVAILABLE);
   }
 
   if (!mDocument) {
     return Err(NS_ERROR_NOT_INITIALIZED);
   }
 
-  nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
+  nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(
+      do_QueryInterface(aInfo.mContent));
   NS_ASSERTION(owningElement, "Element is not a style linking element!");
 
   // Since we're not planning to load a URI, no need to hand a principal to the
-  // load data or to CreateSheet().  Also, OK to use CORS_NONE for the CORS
-  // mode.
+  // load data or to CreateSheet().
 
   StyleSheetState state;
   RefPtr<StyleSheet> sheet;
   IsAlternate isAlternate;
-  nsresult rv = CreateSheet(nullptr, aElement, nullptr, eAuthorSheetFeatures,
-                            CORS_NONE, aReferrerPolicy,
-                            EmptyString(), // no inline integrity checks
-                            false, false, aTitle, state, &isAlternate,
+  nsresult rv = CreateSheet(aInfo,
+                            nullptr,
+                            eAuthorSheetFeatures,
+                            false,
+                            state,
+                            &isAlternate,
                             &sheet);
   if (NS_FAILED(rv)) {
     return Err(rv);
   }
   NS_ASSERTION(state == eSheetNeedsParser,
                "Inline sheets should not be cached");
 
   LOG(("  Sheet is alternate: %d", static_cast<int>(isAlternate)));
 
-  auto matched = PrepareSheet(sheet, aTitle, aMedia, nullptr, isAlternate);
+  auto matched =
+    PrepareSheet(sheet, aInfo.mTitle, aInfo.mMedia, nullptr, isAlternate);
 
-  if (aElement->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
-    ShadowRoot* containingShadow = aElement->GetContainingShadow();
+  if (aInfo.mContent->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
+    ShadowRoot* containingShadow = aInfo.mContent->GetContainingShadow();
     MOZ_ASSERT(containingShadow);
-    containingShadow->InsertSheet(sheet, aElement);
+    containingShadow->InsertSheet(sheet, aInfo.mContent);
   } else {
-    rv = InsertSheetInDoc(sheet, aElement, mDocument);
+    rv = InsertSheetInDoc(sheet, aInfo.mContent, mDocument);
     if (NS_FAILED(rv)) {
       return Err(rv);
     }
   }
 
-  nsIPrincipal* principal = aElement->NodePrincipal();
-  if (aTriggeringPrincipal) {
+  nsIPrincipal* principal = aInfo.mContent->NodePrincipal();
+  if (aInfo.mTriggeringPrincipal) {
     // The triggering principal may be an expanded principal, which is safe to
     // use for URL security checks, but not as the loader principal for a
     // stylesheet. So treat this as principal inheritance, and downgrade if
     // necessary.
-    principal = BasePrincipal::Cast(aTriggeringPrincipal)->PrincipalToInherit();
+    principal =
+      BasePrincipal::Cast(aInfo.mTriggeringPrincipal)->PrincipalToInherit();
   }
 
-  SheetLoadData* data = new SheetLoadData(this, aTitle, nullptr, sheet,
+  SheetLoadData* data = new SheetLoadData(this,
+                                          aInfo.mTitle,
+                                          nullptr,
+                                          sheet,
                                           owningElement,
                                           isAlternate == IsAlternate::Yes,
                                           matched == MediaMatched::Yes,
-                                          aObserver, nullptr,
-                                          static_cast<nsINode*>(aElement));
+                                          aObserver,
+                                          nullptr,
+                                          aInfo.mContent);
 
   // We never actually load this, so just set its principal directly
   sheet->SetPrincipal(principal);
 
   NS_ADDREF(data);
   data->mLineNumber = aLineNumber;
   bool completed = true;
   // Parse completion releases the load data.
@@ -1972,130 +1976,132 @@ Loader::LoadInlineStyle(nsIContent* aEle
   // If completed is true, |data| may well be deleted by now.
   if (!completed) {
     data->mMustNotify = true;
   }
   return LoadSheetResult { completed ? Completed::Yes : Completed::No, isAlternate, matched };
 }
 
 Result<Loader::LoadSheetResult, nsresult>
-Loader::LoadStyleLink(nsIContent* aElement,
-                      nsIURI* aURL,
-                      nsIPrincipal* aTriggeringPrincipal,
-                      const nsAString& aTitle,
-                      const nsAString& aMedia,
-                      bool aHasAlternateRel,
-                      CORSMode aCORSMode,
-                      ReferrerPolicy aReferrerPolicy,
-                      const nsAString& aIntegrity,
+Loader::LoadStyleLink(const StyleSheetInfo& aInfo,
                       nsICSSLoaderObserver* aObserver)
 {
-  NS_PRECONDITION(aURL, "Must have URL to load");
+  MOZ_ASSERT(aInfo.mURI, "Must have URL to load");
   LOG(("css::Loader::LoadStyleLink"));
-  LOG_URI("  Link uri: '%s'", aURL);
-  LOG(("  Link title: '%s'", NS_ConvertUTF16toUTF8(aTitle).get()));
-  LOG(("  Link media: '%s'", NS_ConvertUTF16toUTF8(aMedia).get()));
-  LOG(("  Link alternate rel: %d", aHasAlternateRel));
+  LOG_URI("  Link uri: '%s'", aInfo.mURI);
+  LOG(("  Link title: '%s'", NS_ConvertUTF16toUTF8(aInfo.mTitle).get()));
+  LOG(("  Link media: '%s'", NS_ConvertUTF16toUTF8(aInfo.mMedia).get()));
+  LOG(("  Link alternate rel: %d", aInfo.mHasAlternateRel));
 
   if (!mEnabled) {
     LOG_WARN(("  Not enabled"));
     return Err(NS_ERROR_NOT_AVAILABLE);
   }
 
   if (!mDocument) {
     return Err(NS_ERROR_NOT_INITIALIZED);
   }
 
-  nsIPrincipal* loadingPrincipal = aElement ? aElement->NodePrincipal()
-                                            : mDocument->NodePrincipal();
+  nsIPrincipal* loadingPrincipal = aInfo.mContent
+    ? aInfo.mContent->NodePrincipal()
+    : mDocument->NodePrincipal();
 
-  nsIPrincipal* principal = aTriggeringPrincipal ? aTriggeringPrincipal
-                                                 : loadingPrincipal;
+  nsIPrincipal* principal = aInfo.mTriggeringPrincipal
+    ? aInfo.mTriggeringPrincipal.get()
+    : loadingPrincipal;
 
-  nsISupports* context = aElement;
+  nsINode* context = aInfo.mContent;
   if (!context) {
     context = mDocument;
   }
 
-  nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aURL, context, false);
+  nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aInfo.mURI, context, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     // Don't fire the error event if our document is loaded as data.  We're
     // supposed to not even try to do loads in that case... Unfortunately, we
     // implement that via nsDataDocumentContentPolicy, which doesn't have a good
     // way to communicate back to us that _it_ is the thing that blocked the
     // load.
-    if (aElement && !mDocument->IsLoadedAsData()) {
+    if (aInfo.mContent && !mDocument->IsLoadedAsData()) {
       // Fire an async error event on it.
       RefPtr<AsyncEventDispatcher> loadBlockingAsyncDispatcher =
-        new LoadBlockingAsyncEventDispatcher(aElement,
+        new LoadBlockingAsyncEventDispatcher(aInfo.mContent,
                                              NS_LITERAL_STRING("error"),
                                              false, false);
       loadBlockingAsyncDispatcher->PostDOMEvent();
     }
     return Err(rv);
   }
 
   StyleSheetState state;
   RefPtr<StyleSheet> sheet;
   IsAlternate isAlternate;
-  rv = CreateSheet(aURL, aElement, principal, eAuthorSheetFeatures,
-                   aCORSMode, aReferrerPolicy, aIntegrity, false,
-                   aHasAlternateRel, aTitle, state, &isAlternate,
+  rv = CreateSheet(aInfo,
+                   principal,
+                   eAuthorSheetFeatures,
+                   false,
+                   state,
+                   &isAlternate,
                    &sheet);
   if (NS_FAILED(rv)) {
     return Err(rv);
   }
 
   LOG(("  Sheet is alternate: %d", static_cast<int>(isAlternate)));
 
-  auto matched = PrepareSheet(sheet, aTitle, aMedia, nullptr, isAlternate);
+  auto matched =
+    PrepareSheet(sheet, aInfo.mTitle, aInfo.mMedia, nullptr, isAlternate);
 
   // FIXME(emilio, bug 1410578): Shadow DOM should be handled here too.
-  rv = InsertSheetInDoc(sheet, aElement, mDocument);
+  rv = InsertSheetInDoc(sheet, aInfo.mContent, mDocument);
   if (NS_FAILED(rv)) {
     return Err(rv);
   }
 
-  nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
+  nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(
+    do_QueryInterface(aInfo.mContent));
 
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete: 0x%p", sheet.get()));
     if (aObserver || !mObservers.IsEmpty() || owningElement) {
-      rv = PostLoadEvent(aURL,
+      rv = PostLoadEvent(aInfo.mURI,
                          sheet,
                          aObserver,
                          isAlternate,
                          matched,
                          owningElement);
       if (NS_FAILED(rv)) {
         return Err(rv);
       }
     }
 
     // The load hasn't been completed yet, will be done in PostLoadEvent.
     return LoadSheetResult { Completed::No, isAlternate, matched };
   }
 
-  // Now we need to actually load it
-  nsCOMPtr<nsINode> requestingNode = do_QueryInterface(context);
-  SheetLoadData* data = new SheetLoadData(this, aTitle, aURL, sheet,
+  // Now we need to actually load it.
+  SheetLoadData* data = new SheetLoadData(this,
+                                          aInfo.mTitle,
+                                          aInfo.mURI,
+                                          sheet,
                                           owningElement,
                                           isAlternate == IsAlternate::Yes,
                                           matched == MediaMatched::Yes,
-                                          aObserver, principal, requestingNode);
+                                          aObserver,
+                                          principal,
+                                          context);
   NS_ADDREF(data);
 
   auto result = LoadSheetResult { Completed::No, isAlternate, matched };
 
   MOZ_ASSERT(result.ShouldBlock() == !data->ShouldDefer(),
              "These should better match!");
 
   // If we have to parse and it's a non-blocking non-inline sheet, defer it.
-  if (aURL &&
-      state == eSheetNeedsParser &&
+  if (state == eSheetNeedsParser &&
       mSheets->mLoadingDatas.Count() != 0 &&
       !result.ShouldBlock()) {
     LOG(("  Deferring sheet load"));
     URIPrincipalReferrerPolicyAndCORSModeHashKey key(data->mURI,
                                                      data->mLoaderPrincipal,
                                                      data->mSheet->GetCORSMode(),
                                                      data->mSheet->GetReferrerPolicy());
     mSheets->mPendingDatas.Put(&key, data);
@@ -2169,17 +2175,17 @@ Loader::LoadChildSheet(StyleSheet* aPare
   if (aParentSheet->GetAssociatedDocument()) {
     StyleSheet* topSheet = aParentSheet;
     while (StyleSheet* parent = topSheet->GetParentSheet()) {
       topSheet = parent;
     }
     owningNode = topSheet->GetOwnerNode();
   }
 
-  nsISupports* context = nullptr;
+  nsINode* context = nullptr;
   nsIPrincipal* loadingPrincipal = nullptr;
   if (owningNode) {
     context = owningNode;
     loadingPrincipal = owningNode->NodePrincipal();
   } else if (mDocument) {
     context = mDocument;
     loadingPrincipal = mDocument->NodePrincipal();
   }
@@ -2241,19 +2247,18 @@ Loader::LoadChildSheet(StyleSheet* aPare
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete"));
     // We're completely done.  No need to notify, even, since the
     // @import rule addition/modification will trigger the right style
     // changes automatically.
     return NS_OK;
   }
 
-  nsCOMPtr<nsINode> requestingNode = do_QueryInterface(context);
   SheetLoadData* data = new SheetLoadData(this, aURL, sheet, aParentData,
-                                          observer, principal, requestingNode);
+                                          observer, principal, context);
 
   NS_ADDREF(data);
   bool syncLoad = data->mSyncLoad;
 
   // Load completion will release the data
   rv = LoadSheet(data, state, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -186,20 +186,23 @@ enum StyleSheetState {
   eSheetLoading,
   eSheetComplete
 };
 
 class Loader final {
   typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
 
 public:
+  typedef nsIStyleSheetLinkingElement::Completed Completed;
+  typedef nsIStyleSheetLinkingElement::HasAlternateRel HasAlternateRel;
   typedef nsIStyleSheetLinkingElement::IsAlternate IsAlternate;
+  typedef nsIStyleSheetLinkingElement::IsInline IsInline;
   typedef nsIStyleSheetLinkingElement::MediaMatched MediaMatched;
-  typedef nsIStyleSheetLinkingElement::Completed Completed;
   typedef nsIStyleSheetLinkingElement::Update LoadSheetResult;
+  typedef nsIStyleSheetLinkingElement::StyleSheetInfo StyleSheetInfo;
 
   Loader();
   // aDocGroup is used for dispatching SheetLoadData in PostLoadEvent(). It
   // can be null if you want to use this constructor, and there's no
   // document when the Loader is constructed.
   explicit Loader(mozilla::dom::DocGroup*);
   explicit Loader(nsIDocument*);
 
@@ -225,72 +228,37 @@ public:
 
   /**
    * Load an inline style sheet.  If a successful result is returned and
    * result.WillNotify() is true, then aObserver is guaranteed to be notified
    * asynchronously once the sheet is marked complete.  If an error is
    * returned, or if result.WillNotify() is false, aObserver will not be
    * notified.  In addition to parsing the sheet, this method will insert it
    * into the stylesheet list of this CSSLoader's document.
-   *
-   * @param aElement the element linking to the stylesheet.  This must not be
-   *                 null and must implement nsIStyleSheetLinkingElement.
-   * @param aBuffer the stylesheet data
-   * @param aTriggeringPrincipal The principal of the scripted caller that
-   *                             initiated the load, if available. Otherwise
-   *                             null.
-   * @param aLineNumber the line number at which the stylesheet data started.
-   * @param aTitle the title of the sheet.
-   * @param aMedia the media string for the sheet.
-   * @param aReferrerPolicy the referrer policy for loading the sheet.
    * @param aObserver the observer to notify when the load completes.
    *        May be null.
    */
   Result<LoadSheetResult, nsresult>
-    LoadInlineStyle(nsIContent* aElement,
+    LoadInlineStyle(const StyleSheetInfo&,
                     const nsAString& aBuffer,
-                    nsIPrincipal* aTriggeringPrincipal,
                     uint32_t aLineNumber,
-                    const nsAString& aTitle,
-                    const nsAString& aMedia,
-                    ReferrerPolicy aReferrerPolicy,
                     nsICSSLoaderObserver* aObserver);
 
   /**
    * Load a linked (document) stylesheet.  If a successful result is returned,
    * aObserver is guaranteed to be notified asynchronously once the sheet is
    * loaded and marked complete, i.e., result.WillNotify() will always return
    * true.  If an error is returned, aObserver will not be notified.  In
    * addition to loading the sheet, this method will insert it into the
    * stylesheet list of this CSSLoader's document.
-   *
-   * @param aElement the element linking to the the stylesheet.  May be null.
-   * @param aURL the URL of the sheet.
-   * @param aTriggeringPrincipal the triggering principal for the load. May be
-   *        null, in which case the NodePrincipal() of the element (or
-   *        document if aElement is null) should be used.
-   * @param aTitle the title of the sheet.
-   * @param aMedia the media string for the sheet.
-   * @param aHasAlternateRel whether the rel for this link included
-   *        "alternate".
-   * @param aCORSMode the CORS mode for this load.
    * @param aObserver the observer to notify when the load completes.
    *                  May be null.
    */
   Result<LoadSheetResult, nsresult>
-    LoadStyleLink(nsIContent* aElement,
-                  nsIURI* aURL,
-                  nsIPrincipal* aTriggeringPrincipal,
-                  const nsAString& aTitle,
-                  const nsAString& aMedia,
-                  bool aHasAlternateRel,
-                  CORSMode aCORSMode,
-                  ReferrerPolicy aReferrerPolicy,
-                  const nsAString& aIntegrity,
-                  nsICSSLoaderObserver* aObserver);
+    LoadStyleLink(const StyleSheetInfo&, nsICSSLoaderObserver* aObserver);
 
   /**
    * Load a child (@import-ed) style sheet.  In addition to loading the sheet,
    * this method will insert it into the child sheet list of aParentSheet.  If
    * there is no sheet currently being parsed and the child sheet is not
    * complete when this method returns, then when the child sheet becomes
    * complete aParentSheet will be QIed to nsICSSLoaderObserver and
    * asynchronously notified, just like for LoadStyleLink.  Note that if the
@@ -490,16 +458,39 @@ private:
   already_AddRefed<nsISerialEventTarget> DispatchTarget();
 
   nsresult CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
                               nsIPrincipal* aTriggeringPrincipal,
                               nsIURI* aTargetURI,
                               nsISupports* aContext,
                               bool aIsPreload);
 
+  nsresult CreateSheet(const StyleSheetInfo& aInfo,
+                       nsIPrincipal* aLoaderPrincipal,
+                       css::SheetParsingMode aParsingMode,
+                       bool aSyncLoad,
+                       StyleSheetState& aSheetState,
+                       IsAlternate* aIsAlternate,
+                       RefPtr<StyleSheet>* aSheet)
+  {
+    return CreateSheet(aInfo.mURI,
+                       aInfo.mContent,
+                       aLoaderPrincipal,
+                       aParsingMode,
+                       aInfo.mCORSMode,
+                       aInfo.mReferrerPolicy,
+                       aInfo.mIntegrity,
+                       aSyncLoad,
+                       aInfo.mHasAlternateRel,
+                       aInfo.mTitle,
+                       aSheetState,
+                       aIsAlternate,
+                       aSheet);
+  }
+
   // For inline style, the aURI param is null, but the aLinkingContent
   // must be non-null then.  The loader principal must never be null
   // if aURI is not null.
   // *aIsAlternate is set based on aTitle and aHasAlternateRel.
   nsresult CreateSheet(nsIURI* aURI,
                        nsIContent* aLinkingContent,
                        nsIPrincipal* aLoaderPrincipal,
                        css::SheetParsingMode aParsingMode,