Bug 1041180: Remove deprecated nsIChannelPolicy and use LoadInfo instead (r=sstamm)
☠☠ backed out by 9f5ced212c7d ☠ ☠
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Thu, 02 Oct 2014 23:34:53 -0700
changeset 231750 42614739736dfbdef714203887e68438fe1d9e4d
parent 231749 a2192165100c58c7222b0e1786350504a12e87b3
child 231751 8e64e5a4157c8622f49784e77fdefb4bb0e8a55d
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)
reviewerssstamm
bugs1041180
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 1041180: Remove deprecated nsIChannelPolicy and use LoadInfo instead (r=sstamm)
content/base/src/nsCSPService.cpp
--- a/content/base/src/nsCSPService.cpp
+++ b/content/base/src/nsCSPService.cpp
@@ -13,16 +13,17 @@
 #include "nsCSPService.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsError.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 #include "mozilla/Preferences.h"
 #include "nsIScriptError.h"
 #include "nsContentUtils.h"
+#include "nsContentPolicyUtils.h"
 #include "nsPrincipal.h"
 
 using namespace mozilla;
 
 /* Keeps track of whether or not CSP is enabled */
 bool CSPService::sCSPEnabled = true;
 
 #ifdef PR_LOGGING
@@ -226,63 +227,66 @@ CSPService::ShouldProcess(uint32_t      
 NS_IMETHODIMP
 CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
                                    nsIChannel *newChannel,
                                    uint32_t flags,
                                    nsIAsyncVerifyRedirectCallback *callback)
 {
   nsAsyncRedirectAutoCallback autoCallback(callback);
 
-  // get the Content Security Policy and load type from the property bag
-  nsCOMPtr<nsISupports> policyContainer;
-  nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(oldChannel));
-  if (!props)
+  nsCOMPtr<nsILoadInfo> loadInfo;
+  nsresult rv = oldChannel->GetLoadInfo(getter_AddRefs(loadInfo));
+
+  // if no loadInfo on the channel, nothing for us to do
+  if (!loadInfo) {
     return NS_OK;
+  }
 
-  props->GetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY,
-                                NS_GET_IID(nsISupports),
-                                getter_AddRefs(policyContainer));
+  // The loadInfo must not necessarily contain a Node, hence we try to query
+  // the CSP in the following order:
+  //   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<nsIChannelPolicy> channelPolicy(do_QueryInterface(policyContainer));
-  if (!channelPolicy)
-    return NS_OK;
-
-  nsCOMPtr<nsISupports> supports;
+  nsCOMPtr<nsINode> loadingNode = loadInfo->LoadingNode();
+  nsCOMPtr<nsIPrincipal> principal = loadingNode ?
+                                     loadingNode->NodePrincipal() :
+                                     loadInfo->LoadingPrincipal();
+  NS_ASSERTION(principal, "Can not evaluate CSP without a principal");
   nsCOMPtr<nsIContentSecurityPolicy> csp;
-  channelPolicy->GetContentSecurityPolicy(getter_AddRefs(supports));
-  csp = do_QueryInterface(supports);
-  uint32_t loadType;
-  channelPolicy->GetLoadType(&loadType);
+  rv = principal->GetCsp(getter_AddRefs(csp));
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  // if no CSP in the channelPolicy, nothing for us to add to the channel
-  if (!csp)
+  // if there is no CSP, nothing for us to do
+  if (!csp) {
     return NS_OK;
+  }
 
   /* Since redirecting channels don't call into nsIContentPolicy, we call our
-   * Content Policy implementation directly when redirects occur. When channels
-   * are created using NS_NewChannel(), callers can optionally pass in a
-   * nsIChannelPolicy containing a CSP object and load type, which is placed in
-   * the new channel's property bag. This container is propagated forward when
-   * channels redirect.
+   * Content Policy implementation directly when redirects occur using the
+   * information set in the LoadInfo when channels are created.
+   *
+   * We check if the CSP permits this host for this type of load, if not,
+   * 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;
-  newChannel->GetURI(getter_AddRefs(newUri));
+  rv = newChannel->GetURI(getter_AddRefs(newUri));
+  NS_ENSURE_SUCCESS(rv, rv);
   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;
-  csp->ShouldLoad(loadType,        // load type per nsIContentPolicy (uint32_t)
-                  newUri,          // nsIURI
-                  nullptr,          // nsIURI
-                  nullptr,          // nsISupports
-                  EmptyCString(),  // ACString - MIME guess
-                  originalUri,     // nsISupports - extra
+  csp->ShouldLoad(policyType,     // load type per nsIContentPolicy (uint32_t)
+                  newUri,         // nsIURI
+                  nullptr,        // nsIURI
+                  nullptr,        // nsISupports
+                  EmptyCString(), // ACString - MIME guess
+                  originalUri,    // aMimeTypeGuess
                   &aDecision);
 
 #ifdef PR_LOGGING
   if (newUri) {
     nsAutoCString newUriSpec("None");
     newUri->GetSpec(newUriSpec);
     PR_LOG(gCspPRLog, PR_LOG_DEBUG,
            ("CSPService::AsyncOnChannelRedirect called for %s",
@@ -292,41 +296,14 @@ CSPService::AsyncOnChannelRedirect(nsICh
     PR_LOG(gCspPRLog, PR_LOG_DEBUG,
            ("CSPService::AsyncOnChannelRedirect ALLOWING request."));
   else
     PR_LOG(gCspPRLog, PR_LOG_DEBUG,
            ("CSPService::AsyncOnChannelRedirect CANCELLING request."));
 #endif
 
   // if ShouldLoad doesn't accept the load, cancel the request
-  if (aDecision != 1) {
+  if (!NS_CP_ACCEPTED(aDecision)) {
     autoCallback.DontCallback();
     return NS_BINDING_FAILED;
   }
-
-  // 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;
+  return NS_OK;
 }