зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1589275 - Add an option to provide a custom violation event callback. ?rckerschb r=ckerschb
Differential Revision: https://phabricator.services.mozilla.com/D68496 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
eb4f651b6b
Коммит
70bbf6da2a
|
@ -119,6 +119,18 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
nsIURI* aOriginalURIIfRedirect,
|
||||
bool aSendViolationReports, const nsAString& aNonce,
|
||||
int16_t* outDecision) {
|
||||
return ShouldLoad(AsyncReportViolationCallback(AsyncReportViolation),
|
||||
aContentType, aCSPEventListener, aContentLocation,
|
||||
aRequestContext, aMimeTypeGuess, aOriginalURIIfRedirect,
|
||||
aSendViolationReports, aNonce, outDecision);
|
||||
}
|
||||
|
||||
nsresult nsCSPContext::ShouldLoad(
|
||||
const AsyncReportViolationCallback& aCallback,
|
||||
nsContentPolicyType aContentType, nsICSPEventListener* aCSPEventListener,
|
||||
nsIURI* aContentLocation, nsISupports* aRequestContext,
|
||||
const nsACString& aMimeTypeGuess, nsIURI* aOriginalURIIfRedirect,
|
||||
bool aSendViolationReports, const nsAString& aNonce, int16_t* outDecision) {
|
||||
if (CSPCONTEXTLOGENABLED()) {
|
||||
CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s",
|
||||
aContentLocation->GetSpecOrDefault().get()));
|
||||
|
@ -161,7 +173,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
}
|
||||
|
||||
bool permitted =
|
||||
permitsInternal(dir,
|
||||
permitsInternal(aCallback, dir,
|
||||
nullptr, // aTriggeringElement
|
||||
aCSPEventListener, aContentLocation,
|
||||
aOriginalURIIfRedirect, aNonce, isPreload,
|
||||
|
@ -184,11 +196,12 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
}
|
||||
|
||||
bool nsCSPContext::permitsInternal(
|
||||
CSPDirective aDir, Element* aTriggeringElement,
|
||||
nsICSPEventListener* aCSPEventListener, nsIURI* aContentLocation,
|
||||
nsIURI* aOriginalURIIfRedirect, const nsAString& aNonce, bool aIsPreload,
|
||||
bool aSpecific, bool aSendViolationReports,
|
||||
bool aSendContentLocationInViolationReports, bool aParserCreated) {
|
||||
const AsyncReportViolationCallback& aCallback, CSPDirective aDir,
|
||||
Element* aTriggeringElement, nsICSPEventListener* aCSPEventListener,
|
||||
nsIURI* aContentLocation, nsIURI* aOriginalURIIfRedirect,
|
||||
const nsAString& aNonce, bool aIsPreload, bool aSpecific,
|
||||
bool aSendViolationReports, bool aSendContentLocationInViolationReports,
|
||||
bool aParserCreated) {
|
||||
bool permits = true;
|
||||
|
||||
nsAutoString violatedDirective;
|
||||
|
@ -216,13 +229,12 @@ bool nsCSPContext::permitsInternal(
|
|||
// If GetCallingLocation fails linenumber & columnNumber are set to 0
|
||||
// anyway so we can skip checking if that is the case.
|
||||
}
|
||||
AsyncReportViolation(
|
||||
aTriggeringElement, aCSPEventListener,
|
||||
aCallback(this, aTriggeringElement, aCSPEventListener,
|
||||
(aSendContentLocationInViolationReports ? aContentLocation
|
||||
: nullptr),
|
||||
BlockedContentSource::eUnknown, /* a BlockedContentSource */
|
||||
aOriginalURIIfRedirect, /* in case of redirect originalURI is not
|
||||
null */
|
||||
aOriginalURIIfRedirect, /* in case of redirect originalURI is
|
||||
not null */
|
||||
violatedDirective, p, /* policy index */
|
||||
EmptyString(), /* no observer subject */
|
||||
spec, /* source file */
|
||||
|
@ -506,7 +518,7 @@ void nsCSPContext::reportInlineViolation(
|
|||
columnNumber = aColumnNumber;
|
||||
}
|
||||
|
||||
AsyncReportViolation(aTriggeringElement, aCSPEventListener,
|
||||
AsyncReportViolation(this, aTriggeringElement, aCSPEventListener,
|
||||
nullptr, // aBlockedURI
|
||||
BlockedContentSource::eInline, // aBlockedSource
|
||||
mSelfURI, // aOriginalURI
|
||||
|
@ -600,6 +612,15 @@ NS_IMETHODIMP
|
|||
nsCSPContext::GetAllowsNavigateTo(nsIURI* aURI, bool aIsFormSubmission,
|
||||
bool aWasRedirected, bool aEnforceWhitelist,
|
||||
bool* outAllowsNavigateTo) {
|
||||
return GetAllowsNavigateTo(AsyncReportViolationCallback(AsyncReportViolation),
|
||||
aURI, aIsFormSubmission, aWasRedirected,
|
||||
aEnforceWhitelist, outAllowsNavigateTo);
|
||||
}
|
||||
|
||||
nsresult nsCSPContext::GetAllowsNavigateTo(
|
||||
const AsyncReportViolationCallback& aCallback, nsIURI* aURI,
|
||||
bool aIsFormSubmission, bool aWasRedirected, bool aEnforceWhitelist,
|
||||
bool* outAllowsNavigateTo) {
|
||||
/*
|
||||
* The matrix below shows the different values of (aWasRedirect,
|
||||
* aEnforceWhitelist) for the three different checks we do.
|
||||
|
@ -660,7 +681,8 @@ nsCSPContext::GetAllowsNavigateTo(nsIURI* aURI, bool aIsFormSubmission,
|
|||
}
|
||||
|
||||
// Report the violation
|
||||
nsresult rv = AsyncReportViolation(
|
||||
nsresult rv = aCallback(
|
||||
this,
|
||||
nullptr, // aTriggeringElement
|
||||
nullptr, // aCSPEventListener
|
||||
blockedURIForReporting, // aBlockedURI
|
||||
|
@ -722,11 +744,11 @@ nsCSPContext::GetAllowsNavigateTo(nsIURI* aURI, bool aIsFormSubmission,
|
|||
mPolicies[p]->getDirectiveStringAndReportSampleForContentType( \
|
||||
nsIContentPolicy::TYPE_##contentPolicyType, violatedDirective, \
|
||||
&reportSample); \
|
||||
AsyncReportViolation(aTriggeringElement, aCSPEventListener, nullptr, \
|
||||
blockedContentSource, nullptr, violatedDirective, \
|
||||
p, NS_LITERAL_STRING(observerTopic), aSourceFile, \
|
||||
reportSample ? aScriptSample : EmptyString(), \
|
||||
aLineNum, aColumnNum); \
|
||||
AsyncReportViolation( \
|
||||
this, aTriggeringElement, aCSPEventListener, nullptr, \
|
||||
blockedContentSource, nullptr, violatedDirective, p, \
|
||||
NS_LITERAL_STRING(observerTopic), aSourceFile, \
|
||||
reportSample ? aScriptSample : EmptyString(), aLineNum, aColumnNum); \
|
||||
} \
|
||||
PR_END_MACRO; \
|
||||
break
|
||||
|
@ -1492,24 +1514,25 @@ class CSPReportSenderRunnable final : public Runnable {
|
|||
* source column number of the violation (if available)
|
||||
*/
|
||||
nsresult nsCSPContext::AsyncReportViolation(
|
||||
Element* aTriggeringElement, nsICSPEventListener* aCSPEventListener,
|
||||
nsIURI* aBlockedURI, BlockedContentSource aBlockedContentSource,
|
||||
nsIURI* aOriginalURI, const nsAString& aViolatedDirective,
|
||||
uint32_t aViolatedPolicyIndex, const nsAString& aObserverSubject,
|
||||
const nsAString& aSourceFile, const nsAString& aScriptSample,
|
||||
uint32_t aLineNum, uint32_t aColumnNum) {
|
||||
EnsureIPCPoliciesRead();
|
||||
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
|
||||
nsCSPContext* aContext, Element* aTriggeringElement,
|
||||
nsICSPEventListener* aCSPEventListener, nsIURI* aBlockedURI,
|
||||
BlockedContentSource aBlockedContentSource, nsIURI* aOriginalURI,
|
||||
const nsAString& aViolatedDirective, uint32_t aViolatedPolicyIndex,
|
||||
const nsAString& aObserverSubject, const nsAString& aSourceFile,
|
||||
const nsAString& aScriptSample, uint32_t aLineNum, uint32_t aColumnNum) {
|
||||
aContext->EnsureIPCPoliciesRead();
|
||||
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, aContext->mPolicies.Length() - 1);
|
||||
|
||||
nsCOMPtr<nsIRunnable> task = new CSPReportSenderRunnable(
|
||||
aTriggeringElement, aCSPEventListener, aBlockedURI, aBlockedContentSource,
|
||||
aOriginalURI, aViolatedPolicyIndex,
|
||||
mPolicies[aViolatedPolicyIndex]->getReportOnlyFlag(), aViolatedDirective,
|
||||
aObserverSubject, aSourceFile, aScriptSample, aLineNum, aColumnNum, this);
|
||||
aContext->mPolicies[aViolatedPolicyIndex]->getReportOnlyFlag(),
|
||||
aViolatedDirective, aObserverSubject, aSourceFile, aScriptSample,
|
||||
aLineNum, aColumnNum, aContext);
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
if (mEventTarget) {
|
||||
mEventTarget->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
|
||||
if (aContext->mEventTarget) {
|
||||
aContext->mEventTarget->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
@ -1592,7 +1615,8 @@ nsCSPContext::PermitsAncestry(nsILoadInfo* aLoadInfo,
|
|||
NS_SecurityCompareURIs(ancestorsArray[a], mSelfURI, true);
|
||||
|
||||
bool permits =
|
||||
permitsInternal(nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE,
|
||||
permitsInternal(AsyncReportViolation, // violation callback
|
||||
nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE,
|
||||
nullptr, // triggering element
|
||||
nullptr, // nsICSPEventListener
|
||||
ancestorsArray[a],
|
||||
|
@ -1619,8 +1643,8 @@ nsCSPContext::Permits(Element* aTriggeringElement,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*outPermits =
|
||||
permitsInternal(aDir, aTriggeringElement, aCSPEventListener, aURI,
|
||||
*outPermits = permitsInternal(AsyncReportViolation, aDir, aTriggeringElement,
|
||||
aCSPEventListener, aURI,
|
||||
nullptr, // no original (pre-redirect) URI
|
||||
EmptyString(), // no nonce
|
||||
false, // not a preload.
|
||||
|
|
|
@ -119,8 +119,16 @@ class nsCSPContext : public nsIContentSecurityPolicy {
|
|||
eSelf,
|
||||
};
|
||||
|
||||
nsresult AsyncReportViolation(
|
||||
mozilla::dom::Element* aTriggeringElement,
|
||||
using AsyncReportViolationCallback = std::function<nsresult(
|
||||
nsCSPContext* aContext, mozilla::dom::Element* aTriggeringElement,
|
||||
nsICSPEventListener* aCSPEventListener, nsIURI* aBlockedURI,
|
||||
BlockedContentSource aBlockedContentSource, nsIURI* aOriginalURI,
|
||||
const nsAString& aViolatedDirective, uint32_t aViolatedPolicyIndex,
|
||||
const nsAString& aObserverSubject, const nsAString& aSourceFile,
|
||||
const nsAString& aScriptSample, uint32_t aLineNum, uint32_t aColumnNum)>;
|
||||
|
||||
static nsresult AsyncReportViolation(
|
||||
nsCSPContext* aContext, mozilla::dom::Element* aTriggeringElement,
|
||||
nsICSPEventListener* aCSPEventListener, nsIURI* aBlockedURI,
|
||||
BlockedContentSource aBlockedContentSource, nsIURI* aOriginalURI,
|
||||
const nsAString& aViolatedDirective, uint32_t aViolatedPolicyIndex,
|
||||
|
@ -140,10 +148,25 @@ class nsCSPContext : public nsIContentSecurityPolicy {
|
|||
0);
|
||||
}
|
||||
|
||||
nsresult GetAllowsNavigateTo(const AsyncReportViolationCallback& aCallback,
|
||||
nsIURI* aURI, bool aIsFormSubmission,
|
||||
bool aWasRedirected, bool aEnforceWhitelist,
|
||||
bool* outAllowsNavigateTo);
|
||||
|
||||
nsresult ShouldLoad(const AsyncReportViolationCallback& aCallback,
|
||||
nsContentPolicyType aContentType,
|
||||
nsICSPEventListener* aCSPEventListener,
|
||||
nsIURI* aContentLocation, nsISupports* aRequestContext,
|
||||
const nsACString& aMimeTypeGuess,
|
||||
nsIURI* aOriginalURIIfRedirect,
|
||||
bool aSendViolationReports, const nsAString& aNonce,
|
||||
int16_t* outDecision);
|
||||
|
||||
private:
|
||||
void EnsureIPCPoliciesRead();
|
||||
|
||||
bool permitsInternal(CSPDirective aDir,
|
||||
bool permitsInternal(const AsyncReportViolationCallback& aCallback,
|
||||
CSPDirective aDir,
|
||||
mozilla::dom::Element* aTriggeringElement,
|
||||
nsICSPEventListener* aCSPEventListener,
|
||||
nsIURI* aContentLocation, nsIURI* aOriginalURIIfRedirect,
|
||||
|
|
|
@ -275,6 +275,15 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI,
|
|||
nsIURI* aNewURI,
|
||||
nsILoadInfo* aLoadInfo,
|
||||
Maybe<nsresult>& aCancelCode) {
|
||||
return ConsultCSPForRedirect(nsCSPContext::AsyncReportViolationCallback(
|
||||
nsCSPContext::AsyncReportViolation),
|
||||
aOriginalURI, aNewURI, aLoadInfo, aCancelCode);
|
||||
}
|
||||
|
||||
nsresult CSPService::ConsultCSPForRedirect(
|
||||
const nsCSPContext::AsyncReportViolationCallback& aCallback,
|
||||
nsIURI* aOriginalURI, nsIURI* aNewURI, nsILoadInfo* aLoadInfo,
|
||||
Maybe<nsresult>& aCancelCode) {
|
||||
// Check CSP navigate-to
|
||||
// We need to enforce the CSP of the document that initiated the load,
|
||||
// which is the CSP to inherit.
|
||||
|
@ -282,8 +291,10 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI,
|
|||
aLoadInfo->GetCspToInherit();
|
||||
if (cspToInherit) {
|
||||
bool allowsNavigateTo = false;
|
||||
nsresult rv = cspToInherit->GetAllowsNavigateTo(
|
||||
aNewURI, aLoadInfo->GetIsFormSubmission(), true, /* aWasRedirected */
|
||||
nsresult rv = static_cast<nsCSPContext*>(cspToInherit.get())
|
||||
->GetAllowsNavigateTo(aCallback, aNewURI,
|
||||
aLoadInfo->GetIsFormSubmission(),
|
||||
true, /* aWasRedirected */
|
||||
false, /* aEnforceWhitelist */
|
||||
&allowsNavigateTo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -330,7 +341,8 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI,
|
|||
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp = aLoadInfo->GetPreloadCsp();
|
||||
if (preloadCsp) {
|
||||
// Pass originalURI to indicate the redirect
|
||||
preloadCsp->ShouldLoad(
|
||||
static_cast<nsCSPContext*>(preloadCsp.get())
|
||||
->ShouldLoad(aCallback,
|
||||
policyType, // load type per nsIContentPolicy (uint32_t)
|
||||
cspEventListener,
|
||||
aNewURI, // nsIURI
|
||||
|
@ -354,7 +366,9 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI,
|
|||
nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadInfo->GetCsp();
|
||||
if (csp) {
|
||||
// Pass originalURI to indicate the redirect
|
||||
csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
|
||||
static_cast<nsCSPContext*>(csp.get())->ShouldLoad(
|
||||
aCallback,
|
||||
policyType, // load type per nsIContentPolicy (uint32_t)
|
||||
cspEventListener,
|
||||
aNewURI, // nsIURI
|
||||
requestContext, // nsISupports
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsIChannel.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsCSPContext.h"
|
||||
|
||||
#define CSPSERVICE_CONTRACTID "@mozilla.org/cspservice;1"
|
||||
#define CSPSERVICE_CID \
|
||||
|
@ -42,6 +43,11 @@ class CSPService : public nsIContentPolicy, public nsIChannelEventSink {
|
|||
nsILoadInfo* aLoadInfo,
|
||||
Maybe<nsresult>& aCancelCode);
|
||||
|
||||
static nsresult ConsultCSPForRedirect(
|
||||
const nsCSPContext::AsyncReportViolationCallback& aCallback,
|
||||
nsIURI* aOriginalURI, nsIURI* aNewURI, nsILoadInfo* aLoadInfo,
|
||||
Maybe<nsresult>& aCancelCode);
|
||||
|
||||
protected:
|
||||
virtual ~CSPService();
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче