Bug 1188028 - Use channel->ascynOpen2 in dom/security/nsCSPContext.cpp (r=sicking)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Mon, 27 Jul 2015 11:57:56 -0700
changeset 308161 acc983ca0dec710088764398caba4eb10512de21
parent 308160 efcd4de4006011213159367544ff3fa99b3f6490
child 308162 573a41d3890e2f7a38c30ba7f484099c0bb930b4
push id1040
push userraliiev@mozilla.com
push dateMon, 29 Feb 2016 17:11:22 +0000
treeherdermozilla-release@8c3167321162 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs1188028
milestone45.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 1188028 - Use channel->ascynOpen2 in dom/security/nsCSPContext.cpp (r=sicking)
caps/nsNullPrincipal.h
caps/nsPrincipal.cpp
dom/base/nsDocument.cpp
dom/interfaces/security/nsIContentSecurityPolicy.idl
dom/security/nsCSPContext.cpp
dom/security/nsCSPContext.h
dom/security/nsContentSecurityManager.cpp
dom/security/test/TestCSPParser.cpp
dom/security/test/csp/test_bug949549.html
dom/security/test/unit/test_csp_reports.js
--- a/caps/nsNullPrincipal.h
+++ b/caps/nsNullPrincipal.h
@@ -66,12 +66,11 @@ public:
   bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override
   {
     return aOther == this;
   }
 
   bool MayLoadInternal(nsIURI* aURI) override;
 
   nsCOMPtr<nsIURI> mURI;
-  nsCOMPtr<nsIContentSecurityPolicy> mCSP;
 };
 
 #endif // nsNullPrincipal_h__
--- a/caps/nsPrincipal.cpp
+++ b/caps/nsPrincipal.cpp
@@ -20,16 +20,17 @@
 #include "nsIEffectiveTLDService.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIProtocolHandler.h"
 #include "nsError.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsNetCID.h"
 #include "jswrapper.h"
 
+#include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/HashFunctions.h"
 
 #include "nsIAppsService.h"
 #include "mozIApplication.h"
 
 using namespace mozilla;
@@ -71,17 +72,22 @@ nsPrincipal::InitializeStatics()
 
 nsPrincipal::nsPrincipal()
   : mCodebaseImmutable(false)
   , mDomainImmutable(false)
   , mInitialized(false)
 { }
 
 nsPrincipal::~nsPrincipal()
-{ }
+{ 
+  // let's clear the principal within the csp to avoid a tangling pointer
+  if (mCSP) {
+    static_cast<nsCSPContext*>(mCSP.get())->clearLoadingPrincipal();
+  }
+}
 
 nsresult
 nsPrincipal::Init(nsIURI *aCodebase, const OriginAttributes& aOriginAttributes)
 {
   NS_ENSURE_STATE(!mInitialized);
   NS_ENSURE_ARG(aCodebase);
 
   mInitialized = true;
@@ -399,17 +405,17 @@ nsPrincipal::Read(nsIObjectInputStream* 
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = SetCsp(csp);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // need to link in the CSP context here (link in the URI of the protected
   // resource).
   if (csp) {
-    csp->SetRequestContext(codebase, nullptr, nullptr);
+    csp->SetRequestContext(nullptr, this);
   }
 
   SetDomain(domain);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -2774,17 +2774,17 @@ nsDocument::InitCSP(nsIChannel* aChannel
     return rv;
   }
 
   // used as a "self" identifier for the CSP.
   nsCOMPtr<nsIURI> selfURI;
   aChannel->GetURI(getter_AddRefs(selfURI));
 
   // Store the request context for violation reports
-  csp->SetRequestContext(nullptr, nullptr, aChannel);
+  csp->SetRequestContext(this, nullptr);
 
   // ----- if the doc is an app and we want a default CSP, apply it.
   if (applyAppDefaultCSP) {
     csp->AppendPolicy(appDefaultCSP, false);
   }
 
   // ----- if the doc is an app and specifies a CSP in its manifest, apply it.
   if (applyAppManifestCSP) {
--- a/dom/interfaces/security/nsIContentSecurityPolicy.idl
+++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl
@@ -3,29 +3,30 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISerializable.idl"
 #include "nsIContentPolicy.idl"
 
 interface nsIURI;
 interface nsIChannel;
 interface nsIDocShell;
+interface nsIDOMDocument;
 interface nsIPrincipal;
 interface nsIURI;
 
 /**
  * nsIContentSecurityPolicy
  * Describes an XPCOM component used to model and enforce CSPs.  Instances of
  * this class may have multiple policies within them, but there should only be
  * one of these per document/principal.
  */
 
 typedef unsigned short CSPDirective;
 
-[scriptable, uuid(36c6d419-24c2-40e8-9adb-11d0b1341770)]
+[scriptable, builtinclass, uuid(b756d344-ee2f-44d0-825e-ea4febd0af14)]
 interface nsIContentSecurityPolicy : nsISerializable
 {
   /**
    * Directives supported by Content Security Policy.  These are enums for
    * the CSPDirective type.
    * The NO_DIRECTIVE entry is  used for checking default permissions and
    * returning failure when asking CSP which directive to check.
    *
@@ -168,26 +169,22 @@ interface nsIContentSecurityPolicy : nsI
   const unsigned short VIOLATION_TYPE_INLINE_STYLE  = 3;
   const unsigned short VIOLATION_TYPE_NONCE_SCRIPT  = 4;
   const unsigned short VIOLATION_TYPE_NONCE_STYLE   = 5;
   const unsigned short VIOLATION_TYPE_HASH_SCRIPT   = 6;
   const unsigned short VIOLATION_TYPE_HASH_STYLE    = 7;
 
   /**
    * Called after the CSP object is created to fill in appropriate request
-   * context and give it a reference to its owning principal for violation
-   * report generation.
-   * This will use whatever data is available, choosing earlier arguments first
-   * if multiple are available.  Either way, it will attempt to obtain the URI,
-   * referrer and the principal from whatever is available.  If the channel is
-   * available, it'll also store that for processing policy-uri directives.
+   * context. Either use
+   *  * aDocument (preferred), or if no document is available, then provide
+   *  * aPrincipal
    */
-  void setRequestContext(in nsIURI selfURI,
-                         in nsIURI referrer,
-                         in nsIChannel aChannel);
+  void setRequestContext(in nsIDOMDocument aDocument,
+                         in nsIPrincipal aPrincipal);
 
   /**
    * Verifies ancestry as permitted by the policy.
    *
    * NOTE: Calls to this may trigger violation reports when queried, so this
    * value should not be cached.
    *
    * @param docShell
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -26,21 +26,21 @@
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIStringStream.h"
 #include "nsIUploadChannel.h"
 #include "nsIScriptError.h"
 #include "nsIWebNavigation.h"
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
-#include "nsNullPrincipal.h"
 #include "nsIContentPolicy.h"
 #include "nsSupportsPrimitives.h"
 #include "nsThreadUtils.h"
 #include "nsString.h"
+#include "nsScriptSecurityManager.h"
 #include "nsStringStream.h"
 #include "mozilla/Logging.h"
 #include "mozilla/dom/CSPReportBinding.h"
 #include "mozilla/dom/CSPDictionariesBinding.h"
 #include "mozilla/net/ReferrerPolicy.h"
 #include "nsINetworkInterceptController.h"
 
 using namespace mozilla;
@@ -260,17 +260,19 @@ NS_IMPL_CLASSINFO(nsCSPContext,
                   nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_CSPCONTEXT_CID)
 
 NS_IMPL_ISUPPORTS_CI(nsCSPContext,
                      nsIContentSecurityPolicy,
                      nsISerializable)
 
 nsCSPContext::nsCSPContext()
-  : mSelfURI(nullptr)
+  : mInnerWindowID(0)
+  , mLoadingContext(nullptr)
+  , mLoadingPrincipal(nullptr)
 {
   CSPCONTEXTLOG(("nsCSPContext::nsCSPContext"));
 }
 
 nsCSPContext::~nsCSPContext()
 {
   CSPCONTEXTLOG(("nsCSPContext::~nsCSPContext"));
   for (uint32_t i = 0; i < mPolicies.Length(); i++) {
@@ -585,62 +587,38 @@ nsCSPContext::LogViolationDetails(uint16
     }
   }
   return NS_OK;
 }
 
 #undef CASE_CHECK_AND_REPORT
 
 NS_IMETHODIMP
-nsCSPContext::SetRequestContext(nsIURI* aSelfURI,
-                                nsIURI* aReferrer,
-                                nsIChannel* aChannel)
+nsCSPContext::SetRequestContext(nsIDOMDocument* aDOMDocument,
+                                nsIPrincipal* aPrincipal)
 {
-  NS_PRECONDITION(aSelfURI || aChannel, "Need aSelfURI or aChannel to set the context properly");
-  NS_ENSURE_ARG(aSelfURI || aChannel);
+  NS_PRECONDITION(aDOMDocument || aPrincipal,
+                  "Can't set context without doc or principal");
+  NS_ENSURE_ARG(aDOMDocument || aPrincipal);
 
-  // first use aSelfURI.  If that's not available get the URI from aChannel.
-  mSelfURI = aSelfURI;
-  if (!mSelfURI) {
-    nsresult rv = aChannel->GetURI(getter_AddRefs(mSelfURI));
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (aDOMDocument) {
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDOMDocument);
+    mLoadingContext = do_GetWeakReference(doc);
+    mSelfURI = doc->GetDocumentURI();
+    doc->GetReferrer(mReferrer);
+    mInnerWindowID = doc->InnerWindowID();
+    mCallingChannelLoadGroup = doc->GetDocumentLoadGroup();
+  }
+  else {
+    mLoadingPrincipal = aPrincipal;
+    mLoadingPrincipal->GetURI(getter_AddRefs(mSelfURI));
+    NS_WARNING("No Document in SetRequestContext; can not query loadgroup; sending reports may fail.");
   }
 
-  NS_ASSERTION(mSelfURI, "No aSelfURI and no URI available from channel in SetRequestContext, can not translate 'self' into actual URI");
-
-  if (aChannel) {
-    mInnerWindowID = nsContentUtils::GetInnerWindowID(aChannel);
-    aChannel->GetLoadGroup(getter_AddRefs(mCallingChannelLoadGroup));
-
-    // Storing the nsINode from the LoadInfo of the original channel,
-    // so we can reuse that information when sending reports.
-    nsCOMPtr<nsILoadInfo> loadInfo;
-    aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
-    if (loadInfo) {
-      nsINode* loadingNode = loadInfo->LoadingNode();
-      if (loadingNode) {
-        mLoadingContext = do_GetWeakReference(loadingNode);
-      }
-    }
-  }
-  else {
-    NS_WARNING("Channel needed (but null) in SetRequestContext.  Cannot query loadgroup, which means report sending may fail.");
-  }
-
-  mReferrer = aReferrer;
-  if (!mReferrer) {
-    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
-    if (httpChannel) {
-      httpChannel->GetReferrer(getter_AddRefs(mReferrer));
-    }
-    else {
-      NS_WARNING("Channel provided to SetRequestContext is not an nsIHttpChannel so referrer is not available for reporting." );
-    }
-  }
-
+  NS_ASSERTION(mSelfURI, "mSelfURI not available, can not translate 'self' into actual URI");
   return NS_OK;
 }
 
 /**
  * Sends CSP violation reports to all sources listed under report-uri.
  *
  * @param aBlockedContentSource
  *        Either a CSP Source (like 'self', as string) or nsIURI: the source
@@ -715,20 +693,18 @@ nsCSPContext::SendReports(nsISupports* a
 
   // original-policy
   nsAutoString originalPolicy;
   rv = this->GetPolicy(aViolatedPolicyIndex, originalPolicy);
   NS_ENSURE_SUCCESS(rv, rv);
   report.mCsp_report.mOriginal_policy = originalPolicy;
 
   // referrer
-  if (mReferrer) {
-    nsAutoCString referrerURI;
-    mReferrer->GetSpec(referrerURI);
-    report.mCsp_report.mReferrer = NS_ConvertUTF8toUTF16(referrerURI);
+  if (!mReferrer.IsEmpty()) {
+    report.mCsp_report.mReferrer = mReferrer;
   }
 
   // violated-directive
   report.mCsp_report.mViolated_directive = aViolatedDirective;
 
   // source-file
   if (!aSourceFile.IsEmpty()) {
     // if aSourceFile is a URI, we have to make sure to strip fragments
@@ -760,58 +736,49 @@ nsCSPContext::SendReports(nsISupports* a
     return NS_ERROR_FAILURE;
   }
 
   // ---------- Assembled, now send it to all the report URIs ----------- //
 
   nsTArray<nsString> reportURIs;
   mPolicies[aViolatedPolicyIndex]->getReportURIs(reportURIs);
 
+
+  nsCOMPtr<nsIDocument> doc = do_QueryReferent(mLoadingContext);
   nsCOMPtr<nsIURI> reportURI;
   nsCOMPtr<nsIChannel> reportChannel;
 
-  nsCOMPtr<nsIDOMNode> loadingContext = do_QueryReferent(mLoadingContext);
-  nsCOMPtr<nsINode> loadingNode = do_QueryInterface(loadingContext);
-
   for (uint32_t r = 0; r < reportURIs.Length(); r++) {
     nsAutoCString reportURICstring = NS_ConvertUTF16toUTF8(reportURIs[r]);
     // try to create a new uri from every report-uri string
     rv = NS_NewURI(getter_AddRefs(reportURI), reportURIs[r]);
     if (NS_FAILED(rv)) {
       const char16_t* params[] = { reportURIs[r].get() };
       CSPCONTEXTLOG(("Could not create nsIURI for report URI %s",
                      reportURICstring.get()));
       CSP_LogLocalizedStr(MOZ_UTF16("triedToSendReport"),
                           params, ArrayLength(params),
                           aSourceFile, aScriptSample, aLineNum, 0,
                           nsIScriptError::errorFlag, "CSP", mInnerWindowID);
       continue; // don't return yet, there may be more URIs
     }
 
-    nsIDocShell* docShell = nullptr;
-
     // try to create a new channel for every report-uri
-    if (loadingNode) {
-      nsIDocument* doc = loadingNode->OwnerDoc();
-      if (doc) {
-        docShell = doc->GetDocShell();
-      }
+    if (doc) {
       rv = NS_NewChannel(getter_AddRefs(reportChannel),
                          reportURI,
-                         loadingNode,
-                         nsILoadInfo::SEC_NORMAL,
+                         doc,
+                         nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                          nsIContentPolicy::TYPE_CSP_REPORT);
     }
     else {
-      nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();
-      NS_ENSURE_TRUE(nullPrincipal, NS_ERROR_FAILURE);
       rv = NS_NewChannel(getter_AddRefs(reportChannel),
                          reportURI,
-                         nullPrincipal,
-                         nsILoadInfo::SEC_NORMAL,
+                         mLoadingPrincipal,
+                         nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                          nsIContentPolicy::TYPE_CSP_REPORT);
     }
 
     if (NS_FAILED(rv)) {
       CSPCONTEXTLOG(("Could not create new channel for report URI %s",
                      reportURICstring.get()));
       continue; // don't return yet, there may be more URIs
     }
@@ -836,54 +803,29 @@ nsCSPContext::SendReports(nsISupports* a
     NS_ENSURE_SUCCESS(rv, rv);
     flags |= nsIRequest::LOAD_ANONYMOUS;
     rv = reportChannel->SetLoadFlags(flags);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // we need to set an nsIChannelEventSink on the channel object
     // so we can tell it to not follow redirects when posting the reports
     RefPtr<CSPReportRedirectSink> reportSink = new CSPReportRedirectSink();
-    if (docShell) {
-      nsCOMPtr<nsINetworkInterceptController> interceptController = do_QueryInterface(docShell);
+    if (doc && doc->GetDocShell()) {
+      nsCOMPtr<nsINetworkInterceptController> interceptController =
+        do_QueryInterface(doc->GetDocShell());
       reportSink->SetInterceptController(interceptController);
     }
     reportChannel->SetNotificationCallbacks(reportSink);
 
     // apply the loadgroup from the channel taken by setRequestContext.  If
     // there's no loadgroup, AsyncOpen will fail on process-split necko (since
     // the channel cannot query the iTabChild).
     rv = reportChannel->SetLoadGroup(mCallingChannelLoadGroup);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    // check content policy
-    int16_t shouldLoad = nsIContentPolicy::ACCEPT;
-    nsCOMPtr<nsIContentPolicy> cp = do_GetService(NS_CONTENTPOLICY_CONTRACTID);
-    if (!cp) {
-      return NS_ERROR_FAILURE;
-    }
-
-    rv = cp->ShouldLoad(nsIContentPolicy::TYPE_CSP_REPORT,
-                        reportURI,
-                        mSelfURI,
-                        nullptr,        // Context
-                        EmptyCString(), // mime type
-                        nullptr,        // Extra parameter
-                        nullptr,        // optional request principal
-                        &shouldLoad);
-
-    // refuse to load if we can't do a security check
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (NS_CP_REJECTED(shouldLoad)) {
-      // skip unauthorized URIs
-      CSPCONTEXTLOG(("nsIContentPolicy blocked sending report to %s",
-                     reportURICstring.get()));
-      continue; // don't return yet, there may be more URIs
-    }
-
     // wire in the string input stream to send the report
     nsCOMPtr<nsIStringInputStream> sis(do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID));
     NS_ASSERTION(sis, "nsIStringInputStream is needed but not available to send CSP violation reports");
     rv = sis->SetData(NS_ConvertUTF16toUTF8(csp_report).get(), csp_report.Length());
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(reportChannel));
     NS_ASSERTION(uploadChannel, "nsIUploadChannel is needed but not available to send CSP violation reports");
@@ -892,17 +834,17 @@ nsCSPContext::SendReports(nsISupports* a
 
     // if this is an HTTP channel, set the request method to post
     nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(reportChannel));
     if (httpChannel) {
       httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
     }
 
     RefPtr<CSPViolationReportListener> listener = new CSPViolationReportListener();
-    rv = reportChannel->AsyncOpen(listener, nullptr);
+    rv = reportChannel->AsyncOpen2(listener);
 
     // AsyncOpen should not fail, but could if there's no load group (like if
     // SetRequestContext is not given a channel).  This should fail quietly and
     // not return an error since it's really ok if reports don't go out, but
     // it's good to log the error locally.
 
     if (NS_FAILED(rv)) {
       const char16_t* params[] = { reportURIs[r].get() };
--- a/dom/security/nsCSPContext.h
+++ b/dom/security/nsCSPContext.h
@@ -52,16 +52,23 @@ class nsCSPContext : public nsIContentSe
                                   nsIURI* aOriginalURI,
                                   const nsAString& aViolatedDirective,
                                   uint32_t aViolatedPolicyIndex,
                                   const nsAString& aObserverSubject,
                                   const nsAString& aSourceFile,
                                   const nsAString& aScriptSample,
                                   uint32_t aLineNum);
 
+    // Hands off! Don't call this method unless you know what you
+    // are doing. It's only supposed to be called from within
+    // the principal destructor to avoid a tangling pointer.
+    void clearLoadingPrincipal() {
+      mLoadingPrincipal = nullptr;
+    }
+
   private:
     bool permitsInternal(CSPDirective aDir,
                          nsIURI* aContentLocation,
                          nsIURI* aOriginalURI,
                          const nsAString& aNonce,
                          bool aWasRedirected,
                          bool aIsPreload,
                          bool aSpecific,
@@ -71,23 +78,27 @@ class nsCSPContext : public nsIContentSe
     // helper to report inline script/style violations
     void reportInlineViolation(nsContentPolicyType aContentType,
                                const nsAString& aNonce,
                                const nsAString& aContent,
                                const nsAString& aViolatedDirective,
                                uint32_t aViolatedPolicyIndex,
                                uint32_t aLineNumber);
 
-    nsCOMPtr<nsIURI>                           mReferrer;
+    nsString                                   mReferrer;
     uint64_t                                   mInnerWindowID; // used for web console logging
     nsTArray<nsCSPPolicy*>                     mPolicies;
     nsCOMPtr<nsIURI>                           mSelfURI;
     nsDataHashtable<nsCStringHashKey, int16_t> mShouldLoadCache;
     nsCOMPtr<nsILoadGroup>                     mCallingChannelLoadGroup;
     nsWeakPtr                                  mLoadingContext;
+    // The CSP hangs off the principal, so let's store a raw pointer of the principal
+    // to avoid memory leaks. Within the destructor of the principal we explicitly
+    // set mLoadingPrincipal to null.
+    nsIPrincipal*                              mLoadingPrincipal;
 };
 
 // Class that listens to violation report transmission and logs errors.
 class CSPViolationReportListener : public nsIStreamListener
 {
   public:
     NS_DECL_NSISTREAMLISTENER
     NS_DECL_NSIREQUESTOBSERVER
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -232,19 +232,24 @@ DoContentSecurityChecks(nsIURI* aURI, ns
       }
       requestingContext = aLoadInfo->LoadingNode();
       MOZ_ASSERT(!requestingContext ||
                  requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE,
                  "type_media requires requestingContext of type Element");
       break;
     }
 
-    case nsIContentPolicy::TYPE_WEBSOCKET:
+    case nsIContentPolicy::TYPE_WEBSOCKET: {
+      MOZ_ASSERT(false, "contentPolicyType not supported yet");
+      break;
+    }
+
     case nsIContentPolicy::TYPE_CSP_REPORT: {
-      MOZ_ASSERT(false, "contentPolicyType not supported yet");
+      mimeTypeGuess = EmptyCString();
+      requestingContext = aLoadInfo->LoadingNode();
       break;
     }
 
     case nsIContentPolicy::TYPE_XSLT: {
       mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
       requestingContext = aLoadInfo->LoadingNode();
       MOZ_ASSERT(!requestingContext ||
                  requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
--- a/dom/security/test/TestCSPParser.cpp
+++ b/dom/security/test/TestCSPParser.cpp
@@ -85,49 +85,38 @@ struct PolicyTest
   char policy[kMaxPolicyLength];
   char expectedResult[kMaxPolicyLength];
 };
 
 nsresult runTest(uint32_t aExpectedPolicyCount, // this should be 0 for policies which should fail to parse
                  const char* aPolicy,
                  const char* aExpextedResult) {
 
-  // we init the csp with http://www.selfuri.com
-  nsCOMPtr<nsIURI> selfURI;
-  nsresult rv = NS_NewURI(getter_AddRefs(selfURI), "http://www.selfuri.com");
-  NS_ENSURE_SUCCESS(rv, rv);
-
+  nsresult rv;
   nsCOMPtr<nsIScriptSecurityManager> secman =
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
-     nsCOMPtr<nsIPrincipal> systemPrincipal;
-  rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
+
+  // we init the csp with http://www.selfuri.com
+  nsCOMPtr<nsIURI> selfURI;
+  rv = NS_NewURI(getter_AddRefs(selfURI), "http://www.selfuri.com");
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // we also init the csp with a dummyChannel, which is unused
-  // for the parser tests but surpresses assertions in SetRequestContext.
-  nsCOMPtr<nsIChannel> dummyChannel;
-  rv = NS_NewChannel(getter_AddRefs(dummyChannel),
-                     selfURI,
-                     systemPrincipal,
-                     nsILoadInfo::SEC_NORMAL,
-                     nsIContentPolicy::TYPE_OTHER);
+  nsCOMPtr<nsIPrincipal> selfURIPrincipal;
+  rv = secman->GetSimpleCodebasePrincipal(selfURI, getter_AddRefs(selfURIPrincipal));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // create a CSP object
   nsCOMPtr<nsIContentSecurityPolicy> csp =
     do_CreateInstance(NS_CSPCONTEXT_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // for testing the parser we only need to set selfURI which is needed
-  // to translate the keyword 'self' into an actual URI. All other
-  // arguments can be nullptrs.
-  csp->SetRequestContext(selfURI,
-                         nullptr,  // nsIURI* aReferrer
-                         dummyChannel);
+  // for testing the parser we only need to set a principal which is needed
+  // to translate the keyword 'self' into an actual URI.
+  rv = csp->SetRequestContext(nullptr, selfURIPrincipal);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // append a policy
   nsString policyStr;
   policyStr.AssignASCII(aPolicy);
   rv = csp->AppendPolicy(policyStr, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/security/test/csp/test_bug949549.html
+++ b/dom/security/test/csp/test_bug949549.html
@@ -16,47 +16,39 @@
 
   const csp = SpecialPowers.Cc["@mozilla.org/cspcontext;1"]
               .createInstance(SpecialPowers.Ci.nsIContentSecurityPolicy);
 
   const gManifestURL = "http://www.example.com/chrome/dom/tests/mochitest/webapps/apps/basic.webapp";
 
   SimpleTest.waitForExplicitFinish();
   var app;
+  var principal;
 
   function setupTest() {
     // We have to install an app in order for the app URL to be valid
     // (otherwise we get a "DummyChannel" that throws NS_NOT_IMPLEMENTED)
     SpecialPowers.setAllAppsLaunchable(true);
     SpecialPowers.addPermission("webapps-manage", true, document);
     SpecialPowers.autoConfirmAppInstall(function () {
       let req = navigator.mozApps.install(gManifestURL);
       req.onsuccess = function () {
         app = this.result;
         runTest();
       }
     });
   }
 
   function runTest() {
-    // We have to use a mochitest to test app:// urls,
-    // as app channels can't be instanciated in xpcshell.
-    // Because app protocol depends on webapps.jsm,
-    // which doesn't instanciate properly on xpcshell without many hacks
-    let appchan = SpecialPowers.Services.io.newChannel2(gManifestURL,
-                                                        null,
-                                                        null,
-                                                        null,      // aLoadingNode
-                                                        SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal(),
-                                                        null,      // aTriggeringPrincipal
-                                                        SpecialPowers.Ci.nsILoadInfo.SEC_NORMAL,
-                                                        SpecialPowers.Ci.nsIContentPolicy.TYPE_OTHER);
-
     try {
-      csp.setRequestContext(null, null, appchan);
+      var secMan = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
+                   .getService(SpecialPowers.Ci.nsIScriptSecurityManager);
+      var manifestURI = SpecialPowers.Services.io.newURI(gManifestURL, null, null);
+      principal = secMan.getSimpleCodebasePrincipal(manifestURI);
+      csp.setRequestContext(null, principal);
       ok(true, "setRequestContext hasn't thown");
     } catch(e) {
       ok(false, "setRequestContext throws");
     }
 
     cleanup()
   }
 
--- a/dom/security/test/unit/test_csp_reports.js
+++ b/dom/security/test/unit/test_csp_reports.js
@@ -10,16 +10,18 @@ var Cr = Components.results;
 Cu.import('resource://gre/modules/NetUtil.jsm');
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://testing-common/httpd.js");
 
 var httpServer = new HttpServer();
 httpServer.start(-1);
 var testsToFinish = 0;
 
+var principal;
+
 const REPORT_SERVER_PORT = httpServer.identity.primaryPort;
 const REPORT_SERVER_URI = "http://localhost";
 const REPORT_SERVER_PATH = "/report";
 
 /**
  * Construct a callback that listens to a report submission and either passes
  * or fails a test based on what it gets.
  */
@@ -67,24 +69,23 @@ function makeTest(id, expectedJSON, useR
               .createInstance(Ci.nsIContentSecurityPolicy);
   var policy = "default-src 'none'; " +
                "report-uri " + REPORT_SERVER_URI +
                                ":" + REPORT_SERVER_PORT +
                                "/test" + id;
   var selfuri = NetUtil.newURI(REPORT_SERVER_URI +
                                ":" + REPORT_SERVER_PORT +
                                "/foo/self");
-  var selfchan = NetUtil.newChannel({
-    uri: selfuri,
-    loadUsingSystemPrincipal: true});
 
   dump("Created test " + id + " : " + policy + "\n\n");
 
-  // make the reports seem authentic by "binding" them to a channel.
-  csp.setRequestContext(selfuri, null, selfchan);
+  let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
+              .getService(Ci.nsIScriptSecurityManager);
+  principal = ssm.getSimpleCodebasePrincipal(selfuri);
+  csp.setRequestContext(null, principal);
 
   // Load up the policy
   // set as report-only if that's the case
   csp.appendPolicy(policy, useReportOnlyPolicy);
 
   // prime the report server
   var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON);
   httpServer.registerPathHandler("/test" + id, handler);