Bug 1147996 - Enable interception of CSP reports through service workers; r=nsm
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 26 Mar 2015 13:46:07 -0400
changeset 266693 84792fb8d1bd85d04c49f7f12489871d4757daf5
parent 266692 256a54bc4d9663e8ac7741ec9e95b99d89352607
child 266694 3d57107fcf9f9850148245c39dabd18cdfc6b861
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnsm
bugs1147996, 1147699
milestone39.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 1147996 - Enable interception of CSP reports through service workers; r=nsm Currently when sending a CSP report, HttpBaseChannel::ShouldIntercept tries to get access to the nsINetworkInterceptController interface through the channel's notification callbacks, but in this case the notification callback is the CSPReportRedirectSink object (thanks to nsCORSListenerProxy::Init). This patch extends CSPReportRedirectSink to make it aware of nsINetworkInterceptController, and have it route the request for nsINetworkInterceptController correctly to the docshell without the need to mess with the notification callbacks. This will be tested in bug 1147699.
dom/security/nsCSPContext.cpp
dom/security/nsCSPContext.h
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -32,16 +32,17 @@
 #include "nsNullPrincipal.h"
 #include "nsIContentPolicy.h"
 #include "nsSupportsPrimitives.h"
 #include "nsThreadUtils.h"
 #include "nsString.h"
 #include "prlog.h"
 #include "mozilla/dom/CSPReportBinding.h"
 #include "mozilla/net/ReferrerPolicy.h"
+#include "nsINetworkInterceptController.h"
 
 using namespace mozilla;
 
 #if defined(PR_LOGGING)
 static PRLogModuleInfo *
 GetCspContextLog()
 {
   static PRLogModuleInfo *gCspContextPRLog;
@@ -762,18 +763,24 @@ nsCSPContext::SendReports(nsISupports* a
                      reportURICstring.get()));
       CSP_LogLocalizedStr(NS_LITERAL_STRING("triedToSendReport").get(),
                           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();
+      }
       rv = NS_NewChannel(getter_AddRefs(reportChannel),
                          reportURI,
                          loadingNode,
                          nsILoadInfo::SEC_NORMAL,
                          nsIContentPolicy::TYPE_CSP_REPORT);
     }
     else {
       nsCOMPtr<nsIPrincipal> nullPrincipal =
@@ -812,16 +819,20 @@ 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
     nsRefPtr<CSPReportRedirectSink> reportSink = new CSPReportRedirectSink();
+    if (docShell) {
+      nsCOMPtr<nsINetworkInterceptController> interceptController = do_QueryInterface(docShell);
+      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);
 
@@ -1277,19 +1288,33 @@ CSPReportRedirectSink::AsyncOnChannelRed
                                    NS_LITERAL_STRING("denied redirect while sending violation report").get());
 
   return NS_BINDING_REDIRECTED;
 }
 
 NS_IMETHODIMP
 CSPReportRedirectSink::GetInterface(const nsIID& aIID, void** aResult)
 {
+  if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController)) &&
+      mInterceptController) {
+    nsCOMPtr<nsINetworkInterceptController> copy(mInterceptController);
+    *aResult = copy.forget().take();
+
+    return NS_OK;
+  }
+
   return QueryInterface(aIID, aResult);
 }
 
+void
+CSPReportRedirectSink::SetInterceptController(nsINetworkInterceptController* aInterceptController)
+{
+  mInterceptController = aInterceptController;
+}
+
 /* ===== nsISerializable implementation ====== */
 
 NS_IMETHODIMP
 nsCSPContext::Read(nsIObjectInputStream* aStream)
 {
   nsresult rv;
   nsCOMPtr<nsISupports> supports;
 
--- a/dom/security/nsCSPContext.h
+++ b/dom/security/nsCSPContext.h
@@ -19,16 +19,18 @@
 #include "nsXPCOM.h"
 
 #define NS_CSPCONTEXT_CONTRACTID "@mozilla.org/cspcontext;1"
  // 09d9ed1a-e5d4-4004-bfe0-27ceb923d9ac
 #define NS_CSPCONTEXT_CID \
 { 0x09d9ed1a, 0xe5d4, 0x4004, \
   { 0xbf, 0xe0, 0x27, 0xce, 0xb9, 0x23, 0xd9, 0xac } }
 
+class nsINetworkInterceptController;
+
 class nsCSPContext : public nsIContentSecurityPolicy
 {
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSICONTENTSECURITYPOLICY
     NS_DECL_NSISERIALIZABLE
 
   protected:
@@ -104,13 +106,18 @@ class CSPReportRedirectSink final : publ
   public:
     NS_DECL_NSICHANNELEVENTSINK
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_ISUPPORTS
 
   public:
     CSPReportRedirectSink();
 
+    void SetInterceptController(nsINetworkInterceptController* aInterceptController);
+
   protected:
     virtual ~CSPReportRedirectSink();
+
+  private:
+    nsCOMPtr<nsINetworkInterceptController> mInterceptController;
 };
 
 #endif /* nsCSPContext_h___ */