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.
This commit is contained in:
Ehsan Akhgari 2015-03-26 13:46:07 -04:00
parent b5cfb9bee0
commit f2fdcdb534
2 changed files with 32 additions and 0 deletions

View File

@ -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<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
@ -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<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

View File

@ -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<nsINetworkInterceptController> mInterceptController;
};
#endif /* nsCSPContext_h___ */