Bug 1041180: Remove deprecated nsIChannelPolicy and use LoadInfo instead (r=sstamm)

This commit is contained in:
Christoph Kerschbaumer 2014-10-15 19:12:53 -07:00
parent faccbd4747
commit 43fe8b22ea

View File

@ -18,6 +18,7 @@
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsContentPolicyUtils.h"
#include "nsPrincipal.h" #include "nsPrincipal.h"
using namespace mozilla; using namespace mozilla;
@ -231,53 +232,56 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
{ {
nsAsyncRedirectAutoCallback autoCallback(callback); nsAsyncRedirectAutoCallback autoCallback(callback);
// get the Content Security Policy and load type from the property bag nsCOMPtr<nsILoadInfo> loadInfo;
nsCOMPtr<nsISupports> policyContainer; nsresult rv = oldChannel->GetLoadInfo(getter_AddRefs(loadInfo));
nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(oldChannel));
if (!props) // if no loadInfo on the channel, nothing for us to do
if (!loadInfo) {
return NS_OK; return NS_OK;
}
props->GetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY, // The loadInfo must not necessarily contain a Node, hence we try to query
NS_GET_IID(nsISupports), // the CSP in the following order:
getter_AddRefs(policyContainer)); // a) Get the Node, the Principal of that Node, and the CSP of that Principal
// b) Get the Principal and the CSP of that Principal
// see if we have a valid nsIChannelPolicy containing CSP and load type nsCOMPtr<nsINode> loadingNode = loadInfo->LoadingNode();
nsCOMPtr<nsIChannelPolicy> channelPolicy(do_QueryInterface(policyContainer)); nsCOMPtr<nsIPrincipal> principal = loadingNode ?
if (!channelPolicy) loadingNode->NodePrincipal() :
return NS_OK; loadInfo->LoadingPrincipal();
NS_ASSERTION(principal, "Can not evaluate CSP without a principal");
nsCOMPtr<nsISupports> supports;
nsCOMPtr<nsIContentSecurityPolicy> csp; nsCOMPtr<nsIContentSecurityPolicy> csp;
channelPolicy->GetContentSecurityPolicy(getter_AddRefs(supports)); rv = principal->GetCsp(getter_AddRefs(csp));
csp = do_QueryInterface(supports); NS_ENSURE_SUCCESS(rv, rv);
uint32_t loadType;
channelPolicy->GetLoadType(&loadType);
// if no CSP in the channelPolicy, nothing for us to add to the channel // if there is no CSP, nothing for us to do
if (!csp) if (!csp) {
return NS_OK; return NS_OK;
}
/* Since redirecting channels don't call into nsIContentPolicy, we call our /* Since redirecting channels don't call into nsIContentPolicy, we call our
* Content Policy implementation directly when redirects occur. When channels * Content Policy implementation directly when redirects occur using the
* are created using NS_NewChannel(), callers can optionally pass in a * information set in the LoadInfo when channels are created.
* nsIChannelPolicy containing a CSP object and load type, which is placed in *
* the new channel's property bag. This container is propagated forward when * We check if the CSP permits this host for this type of load, if not,
* channels redirect. * we cancel the load now.
*/ */
// Does the CSP permit this host for this type of load?
// If not, cancel the load now.
nsCOMPtr<nsIURI> newUri; nsCOMPtr<nsIURI> newUri;
newChannel->GetURI(getter_AddRefs(newUri)); rv = newChannel->GetURI(getter_AddRefs(newUri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> originalUri; nsCOMPtr<nsIURI> originalUri;
oldChannel->GetOriginalURI(getter_AddRefs(originalUri)); rv = oldChannel->GetOriginalURI(getter_AddRefs(originalUri));
NS_ENSURE_SUCCESS(rv, rv);
nsContentPolicyType policyType = loadInfo->GetContentPolicyType();
int16_t aDecision = nsIContentPolicy::ACCEPT; int16_t aDecision = nsIContentPolicy::ACCEPT;
csp->ShouldLoad(loadType, // load type per nsIContentPolicy (uint32_t) csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI newUri, // nsIURI
nullptr, // nsIURI nullptr, // nsIURI
nullptr, // nsISupports nullptr, // nsISupports
EmptyCString(), // ACString - MIME guess EmptyCString(), // ACString - MIME guess
originalUri, // nsISupports - extra originalUri, // aMimeTypeGuess
&aDecision); &aDecision);
#ifdef PR_LOGGING #ifdef PR_LOGGING
@ -297,36 +301,9 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
#endif #endif
// if ShouldLoad doesn't accept the load, cancel the request // if ShouldLoad doesn't accept the load, cancel the request
if (aDecision != 1) { if (!NS_CP_ACCEPTED(aDecision)) {
autoCallback.DontCallback(); autoCallback.DontCallback();
return NS_BINDING_FAILED; return NS_BINDING_FAILED;
} }
return NS_OK;
// the redirect is permitted, so propagate the Content Security Policy
// and load type to the redirecting channel
nsresult rv;
nsCOMPtr<nsIWritablePropertyBag2> props2 = do_QueryInterface(newChannel);
if (props2) {
rv = props2->SetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY,
channelPolicy);
if (NS_SUCCEEDED(rv)) {
return NS_OK;
}
}
// The redirecting channel isn't a writable property bag, we won't be able
// to enforce the load policy if it redirects again, so we stop it now.
nsAutoCString newUriSpec;
rv = newUri->GetSpec(newUriSpec);
NS_ConvertUTF8toUTF16 unicodeSpec(newUriSpec);
const char16_t *formatParams[] = { unicodeSpec.get() };
if (NS_SUCCEEDED(rv)) {
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Redirect Error"), nullptr,
nsContentUtils::eDOM_PROPERTIES,
"InvalidRedirectChannelWarning",
formatParams, 1);
}
return NS_BINDING_FAILED;
} }