mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 687086 - change nsIContentSecurityPolicy to return two values, shouldBlock and shouldReportViolation. r=bz
This commit is contained in:
parent
65fa1b988f
commit
525de67a06
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
},
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
Cache-Control: no-cache
|
||||
X-Content-Security-Policy: allow 'self'
|
||||
X-Content-Security-Policy: default-src 'self'
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user