Bug 1195173 - Use channel->ascynOpen2 layout/style/Loader.cpp (r=bz)

This commit is contained in:
Christoph Kerschbaumer 2016-01-26 15:30:47 -08:00
parent 97547e56fc
commit 084f79034a
3 changed files with 62 additions and 146 deletions

View File

@ -143,8 +143,17 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
break; break;
} }
case nsIContentPolicy::TYPE_IMAGE: case nsIContentPolicy::TYPE_IMAGE: {
case nsIContentPolicy::TYPE_STYLESHEET: MOZ_ASSERT(false, "contentPolicyType not supported yet");
break;
}
case nsIContentPolicy::TYPE_STYLESHEET: {
mimeTypeGuess = NS_LITERAL_CSTRING("text/css");
requestingContext = aLoadInfo->LoadingNode();
break;
}
case nsIContentPolicy::TYPE_OBJECT: case nsIContentPolicy::TYPE_OBJECT:
case nsIContentPolicy::TYPE_DOCUMENT: { case nsIContentPolicy::TYPE_DOCUMENT: {
MOZ_ASSERT(false, "contentPolicyType not supported yet"); MOZ_ASSERT(false, "contentPolicyType not supported yet");

View File

@ -48,7 +48,6 @@
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "nsIThreadInternal.h" #include "nsIThreadInternal.h"
#include "nsCORSListenerProxy.h"
#include "nsINetworkPredictor.h" #include "nsINetworkPredictor.h"
#include "mozilla/dom/ShadowRoot.h" #include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/URL.h" #include "mozilla/dom/URL.h"
@ -75,16 +74,14 @@ using namespace mozilla::dom;
* The CSS Loader gets requests to load various sorts of style sheets: * The CSS Loader gets requests to load various sorts of style sheets:
* inline style from <style> elements, linked style, @import-ed child * inline style from <style> elements, linked style, @import-ed child
* sheets, non-document sheets. The loader handles the following tasks: * sheets, non-document sheets. The loader handles the following tasks:
* * 1) Creation of the actual style sheet objects: CreateSheet()
* 1) Checking whether the load is allowed: CheckLoadAllowed() * 2) setting of the right media, title, enabled state, etc on the
* 2) Creation of the actual style sheet objects: CreateSheet()
* 3) setting of the right media, title, enabled state, etc on the
* sheet: PrepareSheet() * sheet: PrepareSheet()
* 4) Insertion of the sheet in the proper cascade order: * 3) Insertion of the sheet in the proper cascade order:
* InsertSheetInDoc() and InsertChildSheet() * InsertSheetInDoc() and InsertChildSheet()
* 5) Load of the sheet: LoadSheet() * 4) Load of the sheet: LoadSheet() including security checks
* 6) Parsing of the sheet: ParseSheet() * 5) Parsing of the sheet: ParseSheet()
* 7) Cleanup: SheetComplete() * 6) Cleanup: SheetComplete()
* *
* The detailed documentation for these functions is found with the * The detailed documentation for these functions is found with the
* function implementations. * function implementations.
@ -1018,63 +1015,6 @@ Loader::ObsoleteSheet(nsIURI* aURI)
return NS_OK; return NS_OK;
} }
/**
* CheckLoadAllowed will return success if the load is allowed,
* failure otherwise.
*
* @param aSourcePrincipal the principal of the node or document or parent
* sheet loading the sheet
* @param aTargetURI the uri of the sheet to be loaded
* @param aContext the node owning the sheet. This is the element or document
* owning the stylesheet (possibly indirectly, for child sheets)
*/
nsresult
Loader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
nsIURI* aTargetURI,
nsISupports* aContext,
bool aIsPreload)
{
LOG(("css::Loader::CheckLoadAllowed"));
nsresult rv;
if (aSourcePrincipal) {
// Check with the security manager
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
rv =
secMan->CheckLoadURIWithPrincipal(aSourcePrincipal, aTargetURI,
nsIScriptSecurityManager::ALLOW_CHROME);
if (NS_FAILED(rv)) { // failure is normal here; don't warn
return rv;
}
LOG((" Passed security check"));
// Check with content policy
nsContentPolicyType contentPolicyType =
aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(contentPolicyType,
aTargetURI,
aSourcePrincipal,
aContext,
NS_LITERAL_CSTRING("text/css"),
nullptr, //extra param
&shouldLoad,
nsContentUtils::GetContentPolicy(),
nsContentUtils::GetSecurityManager());
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
LOG((" Load blocked by content policy"));
return NS_ERROR_CONTENT_BLOCKED;
}
}
return NS_OK;
}
/** /**
* CreateSheet() creates a CSSStyleSheet object for the given URI, * CreateSheet() creates a CSSStyleSheet object for the given URI,
* if any. If there is no URI given, we just create a new style sheet * if any. If there is no URI given, we just create a new style sheet
@ -1446,19 +1386,8 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
return NS_BINDING_ABORTED; return NS_BINDING_ABORTED;
} }
bool inherit = false;
nsIPrincipal* triggeringPrincipal = aLoadData->mLoaderPrincipal; nsIPrincipal* triggeringPrincipal = aLoadData->mLoaderPrincipal;
if (triggeringPrincipal) { if (!triggeringPrincipal) {
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 {
triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
} }
@ -1487,6 +1416,14 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
mDocument); mDocument);
} }
nsSecurityFlags securityFlags =
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
nsILoadInfo::SEC_ALLOW_CHROME;
nsContentPolicyType contentPolicyType =
aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
// Just load it // Just load it
nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsIChannel> channel;
// Note that we are calling NS_NewChannelWithTriggeringPrincipal() with both // Note that we are calling NS_NewChannelWithTriggeringPrincipal() with both
@ -1499,8 +1436,8 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
aLoadData->mURI, aLoadData->mURI,
aLoadData->mRequestingNode, aLoadData->mRequestingNode,
triggeringPrincipal, triggeringPrincipal,
nsILoadInfo::SEC_NORMAL, securityFlags,
nsIContentPolicy::TYPE_OTHER); contentPolicyType);
} }
else { else {
// either we are loading something inside a document, in which case // either we are loading something inside a document, in which case
@ -1511,13 +1448,17 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
rv = NS_NewChannel(getter_AddRefs(channel), rv = NS_NewChannel(getter_AddRefs(channel),
aLoadData->mURI, aLoadData->mURI,
triggeringPrincipal, triggeringPrincipal,
nsILoadInfo::SEC_NORMAL, securityFlags,
nsIContentPolicy::TYPE_OTHER); contentPolicyType);
}
if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to create channel"));
SheetComplete(aLoadData, rv);
return rv;
} }
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInputStream> stream; nsCOMPtr<nsIInputStream> stream;
rv = channel->Open(getter_AddRefs(stream)); rv = channel->Open2(getter_AddRefs(stream));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to open URI synchronously")); LOG_ERROR((" Failed to open URI synchronously"));
@ -1581,20 +1522,30 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
return NS_OK; return NS_OK;
} }
#ifdef DEBUG
mSyncCallback = true;
#endif
nsCOMPtr<nsILoadGroup> loadGroup; nsCOMPtr<nsILoadGroup> loadGroup;
if (mDocument) { if (mDocument) {
loadGroup = mDocument->GetDocumentLoadGroup(); loadGroup = mDocument->GetDocumentLoadGroup();
NS_ASSERTION(loadGroup, // load for a document with no loadgrup indicates that something is
"No loadgroup for stylesheet; onload will fire early"); // completely bogus, let's bail out early.
if (!loadGroup) {
LOG_ERROR((" Failed to query loadGroup from document"));
SheetComplete(aLoadData, NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
} }
}
#ifdef DEBUG
mSyncCallback = true;
#endif
nsLoadFlags securityFlags = nsILoadInfo::SEC_NORMAL; CORSMode ourCORSMode = aLoadData->mSheet->GetCORSMode();
if (inherit) { nsSecurityFlags securityFlags =
securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; ourCORSMode == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS
: nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (ourCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
} }
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
nsContentPolicyType contentPolicyType = nsContentPolicyType contentPolicyType =
aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
@ -1690,35 +1641,13 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
return rv; return rv;
} }
nsCOMPtr<nsIStreamListener> channelListener;
CORSMode ourCORSMode = aLoadData->mSheet->GetCORSMode();
if (ourCORSMode != CORS_NONE) {
bool withCredentials = (ourCORSMode == CORS_USE_CREDENTIALS);
LOG((" Doing CORS-enabled load; credentials %d", withCredentials));
RefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(streamLoader, aLoadData->mLoaderPrincipal,
withCredentials);
rv = corsListener->Init(channel, DataURIHandling::Allow);
if (NS_FAILED(rv)) {
#ifdef DEBUG
mSyncCallback = false;
#endif
LOG_ERROR((" Initial CORS check failed"));
SheetComplete(aLoadData, rv);
return rv;
}
channelListener = corsListener;
} else {
channelListener = streamLoader;
}
if (mDocument) { if (mDocument) {
mozilla::net::PredictorLearn(aLoadData->mURI, mDocument->GetDocumentURI(), mozilla::net::PredictorLearn(aLoadData->mURI, mDocument->GetDocumentURI(),
nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE, nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE,
mDocument); mDocument);
} }
rv = channel->AsyncOpen(channelListener, nullptr); rv = channel->AsyncOpen2(streamLoader);
#ifdef DEBUG #ifdef DEBUG
mSyncCallback = false; mSyncCallback = false;
@ -2061,14 +1990,10 @@ Loader::LoadStyleLink(nsIContent* aElement,
if (!context) { if (!context) {
context = mDocument; context = mDocument;
} }
nsresult rv = CheckLoadAllowed(principal, aURL, context, false);
if (NS_FAILED(rv)) return rv;
LOG((" Passed load check"));
StyleSheetState state; StyleSheetState state;
RefPtr<CSSStyleSheet> sheet; RefPtr<CSSStyleSheet> sheet;
rv = CreateSheet(aURL, aElement, principal, aCORSMode, nsresult rv = CreateSheet(aURL, aElement, principal, aCORSMode,
aReferrerPolicy, aIntegrity, false, aReferrerPolicy, aIntegrity, false,
aHasAlternateRel, aTitle, state, aIsAlternate, aHasAlternateRel, aTitle, state, aIsAlternate,
getter_AddRefs(sheet)); getter_AddRefs(sheet));
@ -2195,12 +2120,6 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet,
context = mDocument; context = mDocument;
} }
nsIPrincipal* principal = aParentSheet->Principal();
nsresult rv = CheckLoadAllowed(principal, aURL, context, false);
if (NS_FAILED(rv)) return rv;
LOG((" Passed load check"));
SheetLoadData* parentData = nullptr; SheetLoadData* parentData = nullptr;
nsCOMPtr<nsICSSLoaderObserver> observer; nsCOMPtr<nsICSSLoaderObserver> observer;
@ -2227,7 +2146,9 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet,
// Now that we know it's safe to load this (passes security check and not a // Now that we know it's safe to load this (passes security check and not a
// loop) do so. // loop) do so.
nsIPrincipal* principal = aParentSheet->Principal();
RefPtr<CSSStyleSheet> sheet; RefPtr<CSSStyleSheet> sheet;
nsresult rv;
StyleSheetState state; StyleSheetState state;
if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, sheet)) { if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, sheet)) {
aParentRule->SetSheet(sheet); aParentRule->SetSheet(sheet);
@ -2351,16 +2272,12 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
nsresult rv = CheckLoadAllowed(aOriginPrincipal, aURL, mDocument, aIsPreload);
if (NS_FAILED(rv)) {
return rv;
}
StyleSheetState state; StyleSheetState state;
bool isAlternate; bool isAlternate;
RefPtr<CSSStyleSheet> sheet; RefPtr<CSSStyleSheet> sheet;
bool syncLoad = (aObserver == nullptr); bool syncLoad = (aObserver == nullptr);
const nsSubstring& empty = EmptyString(); const nsSubstring& empty = EmptyString();
nsresult rv;
rv = CreateSheet(aURL, nullptr, aOriginPrincipal, aCORSMode, rv = CreateSheet(aURL, nullptr, aOriginPrincipal, aCORSMode,
aReferrerPolicy, aIntegrity, syncLoad, false, aReferrerPolicy, aIntegrity, syncLoad, false,

View File

@ -446,16 +446,6 @@ private:
RefPtr<CSSStyleSheet>& aSheet, RefPtr<CSSStyleSheet>& aSheet,
void* aUserData); void* aUserData);
// Note: null aSourcePrincipal indicates that the content policy and
// CheckLoadURI checks should be skipped.
// aIsPreload indicates whether the html parser preloads that
// stylesheet or if it is a regular load.
nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
nsIURI* aTargetURI,
nsISupports* aContext,
bool aIsPreload);
// For inline style, the aURI param is null, but the aLinkingContent // For inline style, the aURI param is null, but the aLinkingContent
// must be non-null then. The loader principal must never be null // must be non-null then. The loader principal must never be null
// if aURI is not null. // if aURI is not null.