Bug 1038756: Callsites creating a channel in /layout/style/ (r=dbaron)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Sun, 21 Sep 2014 09:41:26 -0700
changeset 229728 55806e3e450fdfec0765af4f6cfb61396e997b71
parent 229727 de85d97eac27680338f398df85f3f281a071d200
child 229729 20bb35fc802a6ad8aaf2ff24b0ca47edd979b84a
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1038756
milestone35.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 1038756: Callsites creating a channel in /layout/style/ (r=dbaron)
layout/style/Loader.cpp
layout/style/nsFontFaceLoader.cpp
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -114,36 +114,39 @@ public:
   // Data for loading a sheet linked from a document
   SheetLoadData(Loader* aLoader,
                 const nsSubstring& aTitle,
                 nsIURI* aURI,
                 CSSStyleSheet* aSheet,
                 nsIStyleSheetLinkingElement* aOwningElement,
                 bool aIsAlternate,
                 nsICSSLoaderObserver* aObserver,
-                nsIPrincipal* aLoaderPrincipal);
+                nsIPrincipal* aLoaderPrincipal,
+                nsINode* aRequestingNode);
 
   // Data for loading a sheet linked from an @import rule
   SheetLoadData(Loader* aLoader,
                 nsIURI* aURI,
                 CSSStyleSheet* aSheet,
                 SheetLoadData* aParentData,
                 nsICSSLoaderObserver* aObserver,
-                nsIPrincipal* aLoaderPrincipal);
+                nsIPrincipal* aLoaderPrincipal,
+                nsINode* aRequestingNode);
 
   // Data for loading a non-document sheet
   SheetLoadData(Loader* aLoader,
                 nsIURI* aURI,
                 CSSStyleSheet* aSheet,
                 bool aSyncLoad,
                 bool aAllowUnsafeRules,
                 bool aUseSystemPrincipal,
                 const nsCString& aCharset,
                 nsICSSLoaderObserver* aObserver,
-                nsIPrincipal* aLoaderPrincipal);
+                nsIPrincipal* aLoaderPrincipal,
+                nsINode* aRequestingNode);
 
   already_AddRefed<nsIURI> GetReferrerURI();
 
   void ScheduleLoadEventIfNeeded(nsresult aStatus);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSITHREADOBSERVER
@@ -229,16 +232,19 @@ public:
   nsCOMPtr<nsIStyleSheetLinkingElement> mOwningElement;
 
   // The observer that wishes to be notified of load completion
   nsCOMPtr<nsICSSLoaderObserver>        mObserver;
 
   // The principal that identifies who started loading us.
   nsCOMPtr<nsIPrincipal>                mLoaderPrincipal;
 
+  // The node that identifies who started loading us.
+  nsCOMPtr<nsINode>                     mRequestingNode;
+
   // The charset to use if the transport and sheet don't indicate one.
   // May be empty.  Must be empty if mOwningElement is non-null.
   nsCString                             mCharsetHint;
 
   // The status our load ended up with; this determines whether we
   // should fire error events or load events.  This gets initialized
   // by ScheduleLoadEventIfNeeded, and is only used after that has
   // been called.
@@ -309,17 +315,18 @@ NS_IMPL_ISUPPORTS(SheetLoadData, nsIUnic
 
 SheetLoadData::SheetLoadData(Loader* aLoader,
                              const nsSubstring& aTitle,
                              nsIURI* aURI,
                              CSSStyleSheet* aSheet,
                              nsIStyleSheetLinkingElement* aOwningElement,
                              bool aIsAlternate,
                              nsICSSLoaderObserver* aObserver,
-                             nsIPrincipal* aLoaderPrincipal)
+                             nsIPrincipal* aLoaderPrincipal,
+                             nsINode* aRequestingNode)
   : mLoader(aLoader),
     mTitle(aTitle),
     mURI(aURI),
     mLineNumber(1),
     mSheet(aSheet),
     mNext(nullptr),
     mPendingChildren(0),
     mSyncLoad(false),
@@ -328,27 +335,29 @@ SheetLoadData::SheetLoadData(Loader* aLo
     mIsCancelled(false),
     mMustNotify(false),
     mWasAlternate(aIsAlternate),
     mAllowUnsafeRules(false),
     mUseSystemPrincipal(false),
     mSheetAlreadyComplete(false),
     mOwningElement(aOwningElement),
     mObserver(aObserver),
-    mLoaderPrincipal(aLoaderPrincipal)
+    mLoaderPrincipal(aLoaderPrincipal),
+    mRequestingNode(aRequestingNode)
 {
   NS_PRECONDITION(mLoader, "Must have a loader!");
 }
 
 SheetLoadData::SheetLoadData(Loader* aLoader,
                              nsIURI* aURI,
                              CSSStyleSheet* aSheet,
                              SheetLoadData* aParentData,
                              nsICSSLoaderObserver* aObserver,
-                             nsIPrincipal* aLoaderPrincipal)
+                             nsIPrincipal* aLoaderPrincipal,
+                             nsINode* aRequestingNode)
   : mLoader(aLoader),
     mURI(aURI),
     mLineNumber(1),
     mSheet(aSheet),
     mNext(nullptr),
     mParentData(aParentData),
     mPendingChildren(0),
     mSyncLoad(false),
@@ -357,17 +366,18 @@ SheetLoadData::SheetLoadData(Loader* aLo
     mIsCancelled(false),
     mMustNotify(false),
     mWasAlternate(false),
     mAllowUnsafeRules(false),
     mUseSystemPrincipal(false),
     mSheetAlreadyComplete(false),
     mOwningElement(nullptr),
     mObserver(aObserver),
-    mLoaderPrincipal(aLoaderPrincipal)
+    mLoaderPrincipal(aLoaderPrincipal),
+    mRequestingNode(aRequestingNode)
 {
   NS_PRECONDITION(mLoader, "Must have a loader!");
   if (mParentData) {
     mSyncLoad = mParentData->mSyncLoad;
     mIsNonDocumentSheet = mParentData->mIsNonDocumentSheet;
     mAllowUnsafeRules = mParentData->mAllowUnsafeRules;
     mUseSystemPrincipal = mParentData->mUseSystemPrincipal;
     ++(mParentData->mPendingChildren);
@@ -380,17 +390,18 @@ SheetLoadData::SheetLoadData(Loader* aLo
 SheetLoadData::SheetLoadData(Loader* aLoader,
                              nsIURI* aURI,
                              CSSStyleSheet* aSheet,
                              bool aSyncLoad,
                              bool aAllowUnsafeRules,
                              bool aUseSystemPrincipal,
                              const nsCString& aCharset,
                              nsICSSLoaderObserver* aObserver,
-                             nsIPrincipal* aLoaderPrincipal)
+                             nsIPrincipal* aLoaderPrincipal,
+                             nsINode* aRequestingNode)
   : mLoader(aLoader),
     mURI(aURI),
     mLineNumber(1),
     mSheet(aSheet),
     mNext(nullptr),
     mPendingChildren(0),
     mSyncLoad(aSyncLoad),
     mIsNonDocumentSheet(true),
@@ -399,16 +410,17 @@ SheetLoadData::SheetLoadData(Loader* aLo
     mMustNotify(false),
     mWasAlternate(false),
     mAllowUnsafeRules(aAllowUnsafeRules),
     mUseSystemPrincipal(aUseSystemPrincipal),
     mSheetAlreadyComplete(false),
     mOwningElement(nullptr),
     mObserver(aObserver),
     mLoaderPrincipal(aLoaderPrincipal),
+    mRequestingNode(aRequestingNode),
     mCharsetHint(aCharset)
 {
   NS_PRECONDITION(mLoader, "Must have a loader!");
 
   NS_POSTCONDITION(!mUseSystemPrincipal || mSyncLoad,
                    "Shouldn't use system principal for async loads");
 }
 
@@ -1410,16 +1422,32 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
 
   if (!mDocument && !aLoadData->mIsNonDocumentSheet) {
     // No point starting the load; just release all the data and such.
     LOG_WARN(("  No document and not non-document sheet; pre-dropping load"));
     SheetComplete(aLoadData, NS_BINDING_ABORTED);
     return NS_BINDING_ABORTED;
   }
 
+  bool inherit = false;
+  nsIPrincipal* requestingPrincipal = aLoadData->mLoaderPrincipal;
+  if (requestingPrincipal) {
+    rv = NS_URIChainHasFlags(aLoadData->mURI,
+                             nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
+                             &inherit);
+    inherit =
+      ((NS_SUCCEEDED(rv) && inherit) ||
+       (nsContentUtils::URIIsLocalFile(aLoadData->mURI) &&
+        NS_SUCCEEDED(aLoadData->mLoaderPrincipal->
+                     CheckMayLoad(aLoadData->mURI, false, false))));
+  }
+  else {
+    requestingPrincipal = nsContentUtils::GetSystemPrincipal();
+  }
+
   if (aLoadData->mSyncLoad) {
     LOG(("  Synchronous load"));
     NS_ASSERTION(!aLoadData->mObserver, "Observer for a sync load?");
     NS_ASSERTION(aSheetState == eSheetNeedsParser,
                  "Sync loads can't reuse existing async loads");
 
     // Create a nsIUnicharStreamLoader instance to which we will feed
     // the data from the sync load.  Do this before creating the
@@ -1436,19 +1464,32 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
       mozilla::net::PredictorLearn(aLoadData->mURI, mDocument->GetDocumentURI(),
                                    nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE,
                                    mDocument);
     }
 
     // Just load it
     nsCOMPtr<nsIInputStream> stream;
     nsCOMPtr<nsIChannel> channel;
-    rv = NS_OpenURI(getter_AddRefs(stream), aLoadData->mURI, nullptr,
-                    nullptr, nullptr, nsIRequest::LOAD_NORMAL,
-                    getter_AddRefs(channel));
+    // Note that we are calling NS_OpenURIInternal() with both a node and a
+    // principal.  This is because of a case where the node is the document
+    // being styled and the principal is the stylesheet (perhaps from a
+    // different origin)  that is applying the styles.
+    rv = NS_OpenURIInternal(getter_AddRefs(stream),
+                            aLoadData->mURI,
+                            aLoadData->mRequestingNode,
+                            requestingPrincipal,
+                            nsILoadInfo::SEC_NORMAL,
+                            nsIContentPolicy::TYPE_OTHER,
+                            nullptr,   // aLoadGroup
+                            nullptr,   // aCallbacks
+                            nsIRequest::LOAD_NORMAL,
+                            nullptr,   // aIoService
+                            getter_AddRefs(channel));
+
     if (NS_FAILED(rv)) {
       LOG_ERROR(("  Failed to open URI synchronously"));
       SheetComplete(aLoadData, rv);
       return rv;
     }
 
     NS_ASSERTION(channel, "NS_OpenURI lied?");
 
@@ -1522,21 +1563,37 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
     NS_ENSURE_SUCCESS(rv, rv);
     if (csp) {
       channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
       channelPolicy->SetContentSecurityPolicy(csp);
       channelPolicy->SetLoadType(nsIContentPolicy::TYPE_STYLESHEET);
     }
   }
 
+  nsLoadFlags securityFlags = nsILoadInfo::SEC_NORMAL;
+  if (inherit) {
+    securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
+  }
+
   nsCOMPtr<nsIChannel> channel;
-  rv = NS_NewChannel(getter_AddRefs(channel),
-                     aLoadData->mURI, nullptr, loadGroup, nullptr,
-                     nsIChannel::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI,
-                     channelPolicy);
+  // Note we are calling NS_NewChannelInternal here with a node and a principal.
+  // This is because of a case where the node is the document being styled and
+  // the principal is the stylesheet (perhaps from a different origin)  that is
+  // applying the styles.
+  rv = NS_NewChannelInternal(getter_AddRefs(channel),
+                             aLoadData->mURI,
+                             aLoadData->mRequestingNode,
+                             requestingPrincipal,
+                             securityFlags,
+                             nsIContentPolicy::TYPE_STYLESHEET,
+                             channelPolicy,
+                             loadGroup,
+                             nullptr,   // aCallbacks
+                             nsIChannel::LOAD_NORMAL |
+                             nsIChannel::LOAD_CLASSIFY_URI);
 
   if (NS_FAILED(rv)) {
 #ifdef DEBUG
     mSyncCallback = false;
 #endif
     LOG_ERROR(("  Failed to create channel"));
     SheetComplete(aLoadData, rv);
     return rv;
@@ -1567,34 +1624,16 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
       }
     }
   }
 
   // Now tell the channel we expect text/css data back....  We do
   // this before opening it, so it's only treated as a hint.
   channel->SetContentType(NS_LITERAL_CSTRING("text/css"));
 
-  if (aLoadData->mLoaderPrincipal) {
-    bool inherit;
-    rv = NS_URIChainHasFlags(aLoadData->mURI,
-                             nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
-                             &inherit);
-    inherit =
-      ((NS_SUCCEEDED(rv) && inherit) ||
-       (nsContentUtils::URIIsLocalFile(aLoadData->mURI) &&
-        NS_SUCCEEDED(aLoadData->mLoaderPrincipal->
-                     CheckMayLoad(aLoadData->mURI, false, false))));
-    nsCOMPtr<nsILoadInfo> loadInfo =
-      new LoadInfo(aLoadData->mLoaderPrincipal,
-                   inherit ?
-                     LoadInfo::eInheritPrincipal : LoadInfo::eDontInheritPrincipal,
-                   LoadInfo::eNotSandboxed);
-    channel->SetLoadInfo(loadInfo);
-  }
-
   // We don't have to hold on to the stream loader.  The ownership
   // model is: Necko owns the stream loader, which owns the load data,
   // which owns us
   nsCOMPtr<nsIUnicharStreamLoader> streamLoader;
   rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader), aLoadData);
   if (NS_FAILED(rv)) {
 #ifdef DEBUG
     mSyncCallback = false;
@@ -1912,17 +1951,17 @@ Loader::LoadInlineStyle(nsIContent* aEle
     containingShadow->InsertSheet(sheet, aElement);
   } else {
     rv = InsertSheetInDoc(sheet, aElement, mDocument);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   SheetLoadData* data = new SheetLoadData(this, aTitle, nullptr, sheet,
                                           owningElement, *aIsAlternate,
-                                          aObserver, nullptr);
+                                          aObserver, nullptr, static_cast<nsINode*>(aElement));
 
   // We never actually load this, so just set its principal directly
   sheet->SetPrincipal(aElement->NodePrincipal());
 
   NS_ADDREF(data);
   data->mLineNumber = aLineNumber;
   // Parse completion releases the load data
   rv = ParseSheet(aBuffer, data, *aCompleted);
@@ -1997,19 +2036,20 @@ Loader::LoadStyleLink(nsIContent* aEleme
                          owningElement);
       return rv;
     }
 
     return NS_OK;
   }
 
   // Now we need to actually load it
+  nsCOMPtr<nsINode> requestingNode = do_QueryInterface(context);
   SheetLoadData* data = new SheetLoadData(this, aTitle, aURL, sheet,
                                           owningElement, *aIsAlternate,
-                                          aObserver, principal);
+                                          aObserver, principal, requestingNode);
   NS_ADDREF(data);
 
   // If we have to parse and it's an alternate non-inline, defer it
   if (aURL && state == eSheetNeedsParser && mSheets->mLoadingDatas.Count() != 0 &&
       *aIsAlternate) {
     LOG(("  Deferring alternate sheet load"));
     URIPrincipalAndCORSModeHashKey key(data->mURI, data->mLoaderPrincipal,
                                        data->mSheet->GetCORSMode());
@@ -2147,18 +2187,19 @@ Loader::LoadChildSheet(CSSStyleSheet* aP
   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, parentData,
-                                          observer, principal);
+                                          observer, principal, requestingNode);
 
   NS_ADDREF(data);
   bool syncLoad = data->mSyncLoad;
 
   // Load completion will release the data
   rv = LoadSheet(data, state);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2260,17 +2301,17 @@ Loader::InternalLoadNonDocumentSheet(nsI
       sheet.swap(*aSheet);
     }
     return rv;
   }
 
   SheetLoadData* data =
     new SheetLoadData(this, aURL, sheet, syncLoad, aAllowUnsafeRules,
                       aUseSystemPrincipal, aCharset, aObserver,
-                      aOriginPrincipal);
+                      aOriginPrincipal, mDocument);
 
   NS_ADDREF(data);
   rv = LoadSheet(data, state);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aSheet) {
     sheet.swap(*aSheet);
   }
@@ -2295,17 +2336,18 @@ Loader::PostLoadEvent(nsIURI* aURI,
 
   nsRefPtr<SheetLoadData> evt =
     new SheetLoadData(this, EmptyString(), // title doesn't matter here
                       aURI,
                       aSheet,
                       aElement,
                       aWasAlternate,
                       aObserver,
-                      nullptr);
+                      nullptr,
+                      mDocument);
   NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY);
 
   if (!mPostedEvents.AppendElement(evt)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv = NS_DispatchToCurrentThread(evt);
   if (NS_FAILED(rv)) {
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -335,23 +335,28 @@ nsUserFontSet::StartLoad(gfxUserFontEntr
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   rv = aUserFontEntry->mPrincipal->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
   if (csp) {
     channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
     channelPolicy->SetContentSecurityPolicy(csp);
     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_FONT);
   }
-  rv = NS_NewChannel(getter_AddRefs(channel),
-                     aFontFaceSrc->mURI,
-                     nullptr,
-                     loadGroup,
-                     nullptr,
-                     nsIRequest::LOAD_NORMAL,
-                     channelPolicy);
+  // Note we are calling NS_NewChannelInternal() with both a node and a
+  // principal.  This is because the document where the font is being loaded
+  // might have a different origin from the principal of the stylesheet
+  // that initiated the font load.
+  rv = NS_NewChannelInternal(getter_AddRefs(channel),
+                             aFontFaceSrc->mURI,
+                             ps->GetDocument(),
+                             aUserFontEntry->mPrincipal,
+                             nsILoadInfo::SEC_NORMAL,
+                             nsIContentPolicy::TYPE_FONT,
+                             channelPolicy,
+                             loadGroup);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<nsFontFaceLoader> fontLoader =
     new nsFontFaceLoader(aUserFontEntry, aFontFaceSrc->mURI, this, channel);
 
   if (!fontLoader)
     return NS_ERROR_OUT_OF_MEMORY;
@@ -950,23 +955,32 @@ nsUserFontSet::SyncLoadFontData(gfxUserF
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   rv = aFontToLoad->mPrincipal->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
   if (csp) {
     channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
     channelPolicy->SetContentSecurityPolicy(csp);
     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_FONT);
   }
-  rv = NS_NewChannel(getter_AddRefs(channel),
-                     aFontFaceSrc->mURI,
-                     nullptr,
-                     nullptr,
-                     nullptr,
-                     nsIRequest::LOAD_NORMAL,
-                     channelPolicy);
+
+  nsIPresShell* ps = mPresContext->PresShell();
+  if (!ps) {
+    return NS_ERROR_FAILURE;
+  }
+  // Note we are calling NS_NewChannelInternal() with both a node and a
+  // principal.  This is because the document where the font is being loaded
+  // might have a different origin from the principal of the stylesheet
+  // that initiated the font load.
+  rv = NS_NewChannelInternal(getter_AddRefs(channel),
+                             aFontFaceSrc->mURI,
+                             ps->GetDocument(),
+                             aFontToLoad->mPrincipal,
+                             nsILoadInfo::SEC_NORMAL,
+                             nsIContentPolicy::TYPE_FONT,
+                             channelPolicy);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // blocking stream is OK for data URIs
   nsCOMPtr<nsIInputStream> stream;
   rv = channel->Open(getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, rv);