Bug 687086 - change nsIContentSecurityPolicy to return two values, shouldBlock and shouldReportViolation. r=bz

This commit is contained in:
Sid Stamm 2012-10-15 13:54:58 -07:00
parent 65fa1b988f
commit 525de67a06
13 changed files with 246 additions and 110 deletions

View File

@ -482,7 +482,8 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
return JS_TRUE;
bool evalOK = true;
rv = csp->GetAllowsEval(&evalOK);
bool reportViolation = false;
rv = csp->GetAllowsEval(&reportViolation, &evalOK);
if (NS_FAILED(rv))
{
@ -490,9 +491,7 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
return JS_TRUE; // fail open to not break sites.
}
if (!evalOK) {
// get the script filename, script sample, and line number
// to log with the violation
if (reportViolation) {
nsAutoString fileName;
unsigned lineNum = 0;
NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP");
@ -503,7 +502,6 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
CopyUTF8toUTF16(nsDependentCString(file), fileName);
}
}
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
fileName,
scriptSample,

View File

@ -9,11 +9,11 @@ interface nsIHttpChannel;
interface nsIDocShell;
/**
* nsIContentSecurityPolicy
* nsIContentSecurityPolicy
* Describes an XPCOM component used to model an enforce CSPs.
*/
[scriptable, uuid(d1680bb4-1ac0-4772-9437-1188375e44f2)]
[scriptable, uuid(91E1F257-914C-4D4F-902C-F67F772839AB)]
interface nsIContentSecurityPolicy : nsISupports
{
@ -37,14 +37,30 @@ interface nsIContentSecurityPolicy : nsISupports
/**
* Whether this policy allows in-page script.
* @param shouldReportViolation
* Whether or not the use of inline script should be reported.
* This function always returns "true" for report-only policies, but when
* the report-only policy is violated, shouldReportViolation is true as
* well.
* @return
* Whether or not the effects of the inline script should be allowed
* (block the compilation if false).
*/
readonly attribute boolean allowsInlineScript;
boolean getAllowsInlineScript(out boolean shouldReportViolation);
/**
* whether this policy allows eval and eval-like functions
* such as setTimeout("code string", time).
* @param shouldReportViolation
* Whether or not the use of eval should be reported.
* This function always returns "true" for report-only policies, but when
* the report-only policy is violated, shouldReportViolation is true as
* well.
* @return
* Whether or not the effects of the eval call should be allowed
* (block the call if false).
*/
readonly attribute boolean allowsEval;
boolean getAllowsEval(out boolean shouldReportViolation);
/**
* Log policy violation on the Error Console and send a report if a report-uri
@ -78,7 +94,7 @@ interface nsIContentSecurityPolicy : nsISupports
* a sample of the violating inline script
* @param lineNum
* source line number of the violation (if available)
* @return
* @return
* nothing.
*/
void sendReports(in AString blockedURI,

View File

@ -128,11 +128,19 @@ ContentSecurityPolicy.prototype = {
return this._policy.toString();
},
get allowsInlineScript() {
getAllowsInlineScript: function(shouldReportViolation) {
// report it?
shouldReportViolation.value = !this._policy.allowsInlineScripts;
// allow it to execute?
return this._reportOnlyMode || this._policy.allowsInlineScripts;
},
get allowsEval() {
getAllowsEval: function(shouldReportViolation) {
// report it?
shouldReportViolation.value = !this._policy.allowsEvalInScripts;
// allow it to execute?
return this._reportOnlyMode || this._policy.allowsEvalInScripts;
},

View File

@ -613,12 +613,12 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
if (csp) {
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("New ScriptLoader i ****with CSP****"));
bool inlineOK;
rv = csp->GetAllowsInlineScript(&inlineOK);
bool inlineOK = true;
bool reportViolations = false;
rv = csp->GetAllowsInlineScript(&reportViolations, &inlineOK);
NS_ENSURE_SUCCESS(rv, false);
if (!inlineOK) {
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP blocked inline scripts (2)"));
if (reportViolations) {
// gather information to log with violation report
nsIURI* uri = mDocument->GetDocumentURI();
nsAutoCString asciiSpec;
@ -636,6 +636,10 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
NS_ConvertUTF8toUTF16(asciiSpec),
scriptText,
aElement->GetScriptLineNumber());
}
if (!inlineOK) {
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP blocked inline scripts (2)"));
return false;
}
}

View File

@ -1,2 +1,2 @@
Cache-Control: no-cache
X-Content-Security-Policy: allow 'self'
X-Content-Security-Policy: default-src 'self'

View File

@ -8,10 +8,12 @@ function logResult(str, passed) {
document.body.appendChild(elt);
}
window._testResults = {};
// callback for when stuff is allowed by CSP
var onevalexecuted = (function(window) {
return function(shouldrun, what, data) {
window._testResults[what] = "ran";
window.parent.scriptRan(shouldrun, what, data);
logResult((shouldrun ? "PASS: " : "FAIL: ") + what + " : " + data, shouldrun);
};})(window);
@ -19,6 +21,7 @@ var onevalexecuted = (function(window) {
// callback for when stuff is blocked
var onevalblocked = (function(window) {
return function(shouldrun, what, data) {
window._testResults[what] = "blocked";
window.parent.scriptBlocked(shouldrun, what, data);
logResult((shouldrun ? "FAIL: " : "PASS: ") + what + " : " + data, !shouldrun);
};})(window);
@ -28,26 +31,38 @@ var onevalblocked = (function(window) {
// out.
addEventListener('load', function() {
// setTimeout(String) test -- should pass
try {
setTimeout('onevalexecuted(false, "setTimeout(String)", "setTimeout with a string was enabled.");', 10);
} catch (e) {
onevalblocked(false, "setTimeout(String)",
"setTimeout with a string was blocked");
// setTimeout(String) test -- mutate something in the window._testResults
// obj, then check it.
{
var str_setTimeoutWithStringRan = 'onevalexecuted(false, "setTimeout(String)", "setTimeout with a string was enabled.");';
function fcn_setTimeoutWithStringCheck() {
if (this._testResults["setTimeout(String)"] !== "ran") {
onevalblocked(false, "setTimeout(String)",
"setTimeout with a string was blocked");
}
}
setTimeout(fcn_setTimeoutWithStringCheck.bind(window), 10);
setTimeout(str_setTimeoutWithStringRan, 10);
}
// setTimeout(function) test -- should pass
try {
setTimeout(function() {
onevalexecuted(true, "setTimeout(function)",
"setTimeout with a function was enabled.")
}, 10);
} catch (e) {
onevalblocked(true, "setTimeout(function)",
"setTimeout with a function was blocked");
// setTimeout(function) test -- mutate something in the window._testResults
// obj, then check it.
{
function fcn_setTimeoutWithFunctionRan() {
onevalexecuted(true, "setTimeout(function)",
"setTimeout with a function was enabled.")
}
function fcn_setTimeoutWithFunctionCheck() {
if (this._testResults["setTimeout(function)"] !== "ran") {
onevalblocked(true, "setTimeout(function)",
"setTimeout with a function was blocked");
}
}
setTimeout(fcn_setTimeoutWithFunctionRan.bind(window), 10);
setTimeout(fcn_setTimeoutWithFunctionCheck.bind(window), 10);
}
// eval() test
// eval() test -- should throw exception as per spec
try {
eval('onevalexecuted(false, "eval(String)", "eval() was enabled.");');
} catch (e) {
@ -55,7 +70,7 @@ addEventListener('load', function() {
"eval() was blocked");
}
// eval(foo,bar) test
// eval(foo,bar) test -- should throw exception as per spec
try {
eval('onevalexecuted(false, "eval(String,scope)", "eval() was enabled.");',1);
} catch (e) {
@ -63,7 +78,7 @@ addEventListener('load', function() {
"eval() with scope was blocked");
}
// [foo,bar].sort(eval) test
// [foo,bar].sort(eval) test -- should throw exception as per spec
try {
['onevalexecuted(false, "[String, obj].sort(eval)", "eval() was enabled.");',1].sort(eval);
} catch (e) {
@ -71,7 +86,7 @@ addEventListener('load', function() {
"eval() with scope via sort was blocked");
}
// [].sort.call([foo,bar], eval) test
// [].sort.call([foo,bar], eval) test -- should throw exception as per spec
try {
[].sort.call(['onevalexecuted(false, "[String, obj].sort(eval)", "eval() was enabled.");',1], eval);
} catch (e) {
@ -79,7 +94,7 @@ addEventListener('load', function() {
"eval() with scope via sort/call was blocked");
}
// new Function() test
// new Function() test -- should throw exception as per spec
try {
var fcn = new Function('onevalexecuted(false, "new Function(String)", "new Function(String) was enabled.");');
fcn();

View File

@ -45,7 +45,6 @@ function makeReportHandler(testpath, message, expectedJSON) {
for (var i in expectedJSON)
do_check_eq(expectedJSON[i], reportObj['csp-report'][i]);
// self-destroy
testsToFinish--;
httpServer.registerPathHandler(testpath, null);
if (testsToFinish < 1)
@ -55,7 +54,12 @@ function makeReportHandler(testpath, message, expectedJSON) {
};
}
function makeTest(id, expectedJSON, callback) {
/**
* Everything created by this assumes it will cause a report. If you want to
* add a test here that will *not* cause a report to go out, you're gonna have
* to make sure the test cleans up after itself.
*/
function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
testsToFinish++;
do_test_pending();
@ -79,6 +83,9 @@ function makeTest(id, expectedJSON, callback) {
// Load up the policy
csp.refinePolicy(policy, selfuri, false);
// set as report-only if that's the case
if (useReportOnlyPolicy) csp.reportOnlyMode = true;
// prime the report server
var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON);
httpServer.registerPathHandler("/test" + id, handler);
@ -96,32 +103,82 @@ function run_test() {
httpServer.start(REPORT_SERVER_PORT);
// test that inline script violations cause a report.
makeTest(0, {"blocked-uri": "self"},
makeTest(0, {"blocked-uri": "self"}, false,
function(csp) {
if(!csp.allowsInlineScript) {
// force the logging, since the getter doesn't.
csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT,
selfuri.asciiSpec,
"script sample",
0);
}
let inlineOK = true, oReportViolation = {};
inlineOK = csp.getAllowsInlineScript(oReportViolation);
// this is not a report only policy, so it better block inline scripts
do_check_false(inlineOK);
// ... and cause reports to go out
do_check_true(oReportViolation.value);
// force the logging, since the getter doesn't.
csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT,
selfuri.asciiSpec,
"script sample",
0);
});
makeTest(1, {"blocked-uri": "self"},
// test that eval violations cause a report.
makeTest(1, {"blocked-uri": "self"}, false,
function(csp) {
if(!csp.allowsEval) {
// force the logging, since the getter doesn't.
csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT,
selfuri.asciiSpec,
"script sample",
1);
}
let evalOK = true, oReportViolation = {};
evalOK = csp.getAllowsEval(oReportViolation);
// this is not a report only policy, so it better block eval
do_check_false(evalOK);
// ... and cause reports to go out
do_check_true(oReportViolation.value);
// force the logging, since the getter doesn't.
csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT,
selfuri.asciiSpec,
"script sample",
1);
});
makeTest(2, {"blocked-uri": "http://blocked.test/foo.js"},
makeTest(2, {"blocked-uri": "http://blocked.test/foo.js"}, false,
function(csp) {
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
NetUtil.newURI("http://blocked.test/foo.js"),
null, null, null, null);
});
// test that inline script violations cause a report in report-only policy
makeTest(3, {"blocked-uri": "self"}, true,
function(csp) {
let inlineOK = true, oReportViolation = {};
inlineOK = csp.getAllowsInlineScript(oReportViolation);
// this is a report only policy, so it better allow inline scripts
do_check_true(inlineOK);
// ... but still cause reports to go out
do_check_true(oReportViolation.value);
// force the logging, since the getter doesn't.
csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT,
selfuri.asciiSpec,
"script sample",
3);
});
// test that eval violations cause a report in report-only policy
makeTest(4, {"blocked-uri": "self"}, true,
function(csp) {
let evalOK = true, oReportViolation = {};
evalOK = csp.getAllowsEval(oReportViolation);
// this is a report only policy, so it better allow eval
do_check_true(evalOK);
// ... but still cause reports to go out
do_check_true(oReportViolation.value);
// force the logging, since the getter doesn't.
csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT,
selfuri.asciiSpec,
"script sample",
4);
});
}

View File

@ -669,11 +669,12 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
bool inlineOK;
rv = csp->GetAllowsInlineScript(&inlineOK);
bool inlineOK = true;
bool reportViolations = false;
rv = csp->GetAllowsInlineScript(&reportViolations, &inlineOK);
NS_ENSURE_SUCCESS(rv, rv);
if ( !inlineOK ) {
if (reportViolations) {
// gather information to log with violation report
nsIURI* uri = doc->GetDocumentURI();
nsAutoCString asciiSpec;
@ -693,6 +694,10 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
NS_ConvertUTF8toUTF16(asciiSpec),
scriptSample,
0);
}
// return early if CSP wants us to block inline scripts
if (!inlineOK) {
return NS_OK;
}
}

View File

@ -245,16 +245,32 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
bool allowsEval;
// this call will send violation reports as warranted (and return true if
// reportOnly is set).
rv = csp->GetAllowsEval(&allowsEval);
bool allowsEval = true;
bool reportViolation = false;
rv = csp->GetAllowsEval(&reportViolation, &allowsEval);
NS_ENSURE_SUCCESS(rv, rv);
if (!allowsEval) {
::JS_ReportError(cx, "call to %s blocked by CSP",
*aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
if (reportViolation) {
// TODO : FIX DATA in violation report.
NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP");
// Get the calling location.
uint32_t lineNum = 0;
const char *fileName;
nsAutoCString aFileName;
if (nsJSUtils::GetCallingLocation(cx, &fileName, &lineNum)) {
aFileName.Assign(fileName);
} else {
aFileName.Assign("unknown");
}
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
NS_ConvertUTF8toUTF16(aFileName),
scriptSample,
lineNum);
}
if (!allowsEval) {
// Note: Our only caller knows to turn NS_ERROR_DOM_TYPE_ERR into NS_OK.
return NS_ERROR_DOM_TYPE_ERR;
}

View File

@ -168,22 +168,27 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
bool allowsInline;
rv = csp->GetAllowsInlineScript(&allowsInline);
NS_ENSURE_SUCCESS(rv, rv);
bool allowsInline = true;
bool reportViolations = false;
rv = csp->GetAllowsInlineScript(&reportViolations, &allowsInline);
NS_ENSURE_SUCCESS(rv, rv);
if (!allowsInline) {
// gather information to log with violation report
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
nsAutoCString asciiSpec;
uri->GetAsciiSpec(asciiSpec);
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT,
NS_ConvertUTF8toUTF16(asciiSpec),
NS_ConvertUTF8toUTF16(mURL),
0);
if (reportViolations) {
// gather information to log with violation report
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
nsAutoCString asciiSpec;
uri->GetAsciiSpec(asciiSpec);
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT,
NS_ConvertUTF8toUTF16(asciiSpec),
NS_ConvertUTF8toUTF16(mURL),
0);
}
//return early if inline scripts are not allowed
if (!allowsInline) {
return NS_ERROR_DOM_RETVAL_UNDEFINED;
}
}
}
// Get the global object we should be running on.

View File

@ -340,7 +340,7 @@ public:
NS_NAMED_LITERAL_STRING(scriptSample,
"Call to eval() or related function blocked by CSP.");
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
mFileName, scriptSample, mLineNum);
mFileName, scriptSample, mLineNum);
}
nsRefPtr<LogViolationDetailsResponseRunnable> response =
@ -359,30 +359,28 @@ ContentSecurityPolicyAllows(JSContext* aCx)
WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
worker->AssertIsOnWorkerThread();
if (worker->IsEvalAllowed()) {
return true;
if (worker->GetReportCSPViolations()) {
nsString fileName;
uint32_t lineNum = 0;
JSScript* script;
const char* file;
if (JS_DescribeScriptedCaller(aCx, &script, &lineNum) &&
(file = JS_GetScriptFilename(aCx, script))) {
fileName.AssignASCII(file);
} else {
JS_ReportPendingException(aCx);
}
nsRefPtr<LogViolationDetailsRunnable> runnable =
new LogViolationDetailsRunnable(worker, fileName, lineNum);
if (!runnable->Dispatch(aCx)) {
JS_ReportPendingException(aCx);
}
}
nsString fileName;
uint32_t lineNum = 0;
JSScript* script;
const char* file;
if (JS_DescribeScriptedCaller(aCx, &script, &lineNum) &&
(file = JS_GetScriptFilename(aCx, script))) {
fileName.AssignASCII(file);
} else {
JS_ReportPendingException(aCx);
}
nsRefPtr<LogViolationDetailsRunnable> runnable =
new LogViolationDetailsRunnable(worker, fileName, lineNum);
if (!runnable->Dispatch(aCx)) {
JS_ReportPendingException(aCx);
}
return false;
return worker->IsEvalAllowed();
}
void

View File

@ -1838,7 +1838,8 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
nsCOMPtr<nsIPrincipal>& aPrincipal,
nsCOMPtr<nsIChannel>& aChannel,
nsCOMPtr<nsIContentSecurityPolicy>& aCSP,
bool aEvalAllowed)
bool aEvalAllowed,
bool aReportCSPViolations)
: EventTarget(aParent ? aCx : NULL), mMutex("WorkerPrivateParent Mutex"),
mCondVar(mMutex, "WorkerPrivateParent CondVar"),
mMemoryReportCondVar(mMutex, "WorkerPrivateParent Memory Report CondVar"),
@ -1848,7 +1849,8 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
mJSRuntimeHeapSize(0), mJSWorkerAllocationThreshold(3),
mGCZeal(0), mJSObjectRooted(false), mParentSuspended(false),
mIsChromeWorker(aIsChromeWorker), mPrincipalIsSystem(false),
mMainThreadObjectsForgotten(false), mEvalAllowed(aEvalAllowed)
mMainThreadObjectsForgotten(false), mEvalAllowed(aEvalAllowed),
mReportCSPViolations(aReportCSPViolations)
{
MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivateParent);
@ -2426,11 +2428,13 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx, JSObject* aObject,
nsCOMPtr<nsIChannel>& aChannel,
nsCOMPtr<nsIContentSecurityPolicy>& aCSP,
bool aEvalAllowed,
bool aReportCSPViolations,
bool aXHRParamsAllowed)
: WorkerPrivateParent<WorkerPrivate>(aCx, aObject, aParent, aParentJSContext,
aScriptURL, aIsChromeWorker, aDomain,
aWindow, aParentScriptContext, aBaseURI,
aPrincipal, aChannel, aCSP, aEvalAllowed),
aPrincipal, aChannel, aCSP, aEvalAllowed,
aReportCSPViolations),
mJSContext(nullptr), mErrorHandlerRecursionCount(0), mNextTimeoutId(1),
mStatus(Pending), mSuspended(false), mTimerRunning(false),
mRunningExpiredTimeouts(false), mCloseHandlerStarted(false),
@ -2459,6 +2463,7 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
nsCOMPtr<nsIContentSecurityPolicy> csp;
bool evalAllowed = true;
bool reportEvalViolations = false;
JSContext* parentContext;
@ -2623,7 +2628,7 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
return nullptr;
}
if (csp && NS_FAILED(csp->GetAllowsEval(&evalAllowed))) {
if (csp && NS_FAILED(csp->GetAllowsEval(&reportEvalViolations, &evalAllowed))) {
NS_ERROR("CSP: failed to get allowsEval");
return nullptr;
}
@ -2682,7 +2687,8 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
nsRefPtr<WorkerPrivate> worker =
new WorkerPrivate(aCx, aObj, aParent, parentContext, scriptURL,
aIsChromeWorker, domain, window, scriptContext, baseURI,
principal, channel, csp, evalAllowed, xhrParamsAllowed);
principal, channel, csp, evalAllowed, reportEvalViolations,
xhrParamsAllowed);
worker->SetIsDOMBinding();
worker->SetWrapper(aObj);

View File

@ -284,6 +284,7 @@ private:
bool mPrincipalIsSystem;
bool mMainThreadObjectsForgotten;
bool mEvalAllowed;
bool mReportCSPViolations;
protected:
WorkerPrivateParent(JSContext* aCx, JSObject* aObject, WorkerPrivate* aParent,
@ -295,7 +296,8 @@ protected:
nsCOMPtr<nsIPrincipal>& aPrincipal,
nsCOMPtr<nsIChannel>& aChannel,
nsCOMPtr<nsIContentSecurityPolicy>& aCSP,
bool aEvalAllowed);
bool aEvalAllowed,
bool aReportCSPViolations);
~WorkerPrivateParent();
@ -560,6 +562,12 @@ public:
mEvalAllowed = aEvalAllowed;
}
bool
GetReportCSPViolations() const
{
return mReportCSPViolations;
}
LocationInfo&
GetLocationInfo()
{
@ -894,7 +902,7 @@ private:
nsCOMPtr<nsIURI>& aBaseURI, nsCOMPtr<nsIPrincipal>& aPrincipal,
nsCOMPtr<nsIChannel>& aChannel,
nsCOMPtr<nsIContentSecurityPolicy>& aCSP, bool aEvalAllowed,
bool aXHRParamsAllowed);
bool aReportCSPViolations, bool aXHRParamsAllowed);
static bool
GetContentSecurityPolicy(JSContext *aCx,