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

This commit is contained in:
Christoph Kerschbaumer 2016-02-02 20:35:02 -08:00
parent 44189c670b
commit 5a89bae2c9
3 changed files with 64 additions and 146 deletions

View File

@ -143,8 +143,17 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
break;
}
case nsIContentPolicy::TYPE_IMAGE:
case nsIContentPolicy::TYPE_STYLESHEET:
case nsIContentPolicy::TYPE_IMAGE: {
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_DOCUMENT: {
MOZ_ASSERT(false, "contentPolicyType not supported yet");

View File

@ -48,7 +48,6 @@
#include "nsThreadUtils.h"
#include "nsGkAtoms.h"
#include "nsIThreadInternal.h"
#include "nsCORSListenerProxy.h"
#include "nsINetworkPredictor.h"
#include "mozilla/dom/ShadowRoot.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:
* inline style from <style> elements, linked style, @import-ed child
* sheets, non-document sheets. The loader handles the following tasks:
*
* 1) Checking whether the load is allowed: CheckLoadAllowed()
* 2) Creation of the actual style sheet objects: CreateSheet()
* 3) setting of the right media, title, enabled state, etc on the
* 1) Creation of the actual style sheet objects: CreateSheet()
* 2) setting of the right media, title, enabled state, etc on the
* 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()
* 5) Load of the sheet: LoadSheet()
* 6) Parsing of the sheet: ParseSheet()
* 7) Cleanup: SheetComplete()
* 4) Load of the sheet: LoadSheet() including security checks
* 5) Parsing of the sheet: ParseSheet()
* 6) Cleanup: SheetComplete()
*
* The detailed documentation for these functions is found with the
* function implementations.
@ -1018,63 +1015,6 @@ Loader::ObsoleteSheet(nsIURI* aURI)
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,
* 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;
}
bool inherit = false;
nsIPrincipal* triggeringPrincipal = aLoadData->mLoaderPrincipal;
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 {
if (!triggeringPrincipal) {
triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
}
@ -1487,6 +1416,14 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
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
nsCOMPtr<nsIChannel> channel;
// Note that we are calling NS_NewChannelWithTriggeringPrincipal() with both
@ -1499,8 +1436,8 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
aLoadData->mURI,
aLoadData->mRequestingNode,
triggeringPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER);
securityFlags,
contentPolicyType);
}
else {
// 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),
aLoadData->mURI,
triggeringPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER);
securityFlags,
contentPolicyType);
}
if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to create channel"));
SheetComplete(aLoadData, rv);
return rv;
}
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInputStream> stream;
rv = channel->Open(getter_AddRefs(stream));
rv = channel->Open2(getter_AddRefs(stream));
if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to open URI synchronously"));
@ -1581,20 +1522,32 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
return NS_OK;
}
#ifdef DEBUG
mSyncCallback = true;
#endif
nsCOMPtr<nsILoadGroup> loadGroup;
if (mDocument) {
loadGroup = mDocument->GetDocumentLoadGroup();
NS_ASSERTION(loadGroup,
"No loadgroup for stylesheet; onload will fire early");
// load for a document with no loadgrup indicates that something is
// 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;
if (inherit) {
securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
CORSMode ourCORSMode = aLoadData->mSheet->GetCORSMode();
nsSecurityFlags securityFlags =
ourCORSMode == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS
: nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (ourCORSMode == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (ourCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
nsContentPolicyType contentPolicyType =
aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
@ -1690,35 +1643,13 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
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) {
mozilla::net::PredictorLearn(aLoadData->mURI, mDocument->GetDocumentURI(),
nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE,
mDocument);
}
rv = channel->AsyncOpen(channelListener, nullptr);
rv = channel->AsyncOpen2(streamLoader);
#ifdef DEBUG
mSyncCallback = false;
@ -2061,17 +1992,13 @@ Loader::LoadStyleLink(nsIContent* aElement,
if (!context) {
context = mDocument;
}
nsresult rv = CheckLoadAllowed(principal, aURL, context, false);
if (NS_FAILED(rv)) return rv;
LOG((" Passed load check"));
StyleSheetState state;
RefPtr<CSSStyleSheet> sheet;
rv = CreateSheet(aURL, aElement, principal, aCORSMode,
aReferrerPolicy, aIntegrity, false,
aHasAlternateRel, aTitle, state, aIsAlternate,
getter_AddRefs(sheet));
nsresult rv = CreateSheet(aURL, aElement, principal, aCORSMode,
aReferrerPolicy, aIntegrity, false,
aHasAlternateRel, aTitle, state, aIsAlternate,
getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
LOG((" Sheet is alternate: %d", *aIsAlternate));
@ -2195,12 +2122,6 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet,
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;
nsCOMPtr<nsICSSLoaderObserver> observer;
@ -2227,7 +2148,9 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet,
// Now that we know it's safe to load this (passes security check and not a
// loop) do so.
nsIPrincipal* principal = aParentSheet->Principal();
RefPtr<CSSStyleSheet> sheet;
nsresult rv;
StyleSheetState state;
if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, sheet)) {
aParentRule->SetSheet(sheet);
@ -2351,16 +2274,12 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = CheckLoadAllowed(aOriginPrincipal, aURL, mDocument, aIsPreload);
if (NS_FAILED(rv)) {
return rv;
}
StyleSheetState state;
bool isAlternate;
RefPtr<CSSStyleSheet> sheet;
bool syncLoad = (aObserver == nullptr);
const nsSubstring& empty = EmptyString();
nsresult rv;
rv = CreateSheet(aURL, nullptr, aOriginPrincipal, aCORSMode,
aReferrerPolicy, aIntegrity, syncLoad, false,

View File

@ -441,16 +441,6 @@ public:
private:
friend class SheetLoadData;
// 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
// must be non-null then. The loader principal must never be null
// if aURI is not null.