From f2fdcdb53467962ff50c4e0a9514b8d607f2bfef Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Thu, 26 Mar 2015 13:46:07 -0400 Subject: [PATCH] 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 | 25 +++++++++++++++++++++++++ dom/security/nsCSPContext.h | 7 +++++++ 2 files changed, 32 insertions(+) diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index 4acce13dc75..c5d636533b8 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -37,6 +37,7 @@ #include "prlog.h" #include "mozilla/dom/CSPReportBinding.h" #include "mozilla/net/ReferrerPolicy.h" +#include "nsINetworkInterceptController.h" using namespace mozilla; @@ -767,8 +768,14 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource, 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, @@ -817,6 +824,10 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource, // we need to set an nsIChannelEventSink on the channel object // so we can tell it to not follow redirects when posting the reports nsRefPtr reportSink = new CSPReportRedirectSink(); + if (docShell) { + nsCOMPtr interceptController = do_QueryInterface(docShell); + reportSink->SetInterceptController(interceptController); + } reportChannel->SetNotificationCallbacks(reportSink); // apply the loadgroup from the channel taken by setRequestContext. If @@ -1282,9 +1293,23 @@ CSPReportRedirectSink::AsyncOnChannelRedirect(nsIChannel* aOldChannel, NS_IMETHODIMP CSPReportRedirectSink::GetInterface(const nsIID& aIID, void** aResult) { + if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController)) && + mInterceptController) { + nsCOMPtr copy(mInterceptController); + *aResult = copy.forget().take(); + + return NS_OK; + } + return QueryInterface(aIID, aResult); } +void +CSPReportRedirectSink::SetInterceptController(nsINetworkInterceptController* aInterceptController) +{ + mInterceptController = aInterceptController; +} + /* ===== nsISerializable implementation ====== */ NS_IMETHODIMP diff --git a/dom/security/nsCSPContext.h b/dom/security/nsCSPContext.h index 9f38b1abe32..9d3ed3faeae 100644 --- a/dom/security/nsCSPContext.h +++ b/dom/security/nsCSPContext.h @@ -24,6 +24,8 @@ { 0x09d9ed1a, 0xe5d4, 0x4004, \ { 0xbf, 0xe0, 0x27, 0xce, 0xb9, 0x23, 0xd9, 0xac } } +class nsINetworkInterceptController; + class nsCSPContext : public nsIContentSecurityPolicy { public: @@ -109,8 +111,13 @@ class CSPReportRedirectSink final : public nsIChannelEventSink, public: CSPReportRedirectSink(); + void SetInterceptController(nsINetworkInterceptController* aInterceptController); + protected: virtual ~CSPReportRedirectSink(); + + private: + nsCOMPtr mInterceptController; }; #endif /* nsCSPContext_h___ */