mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 770099 - Send CSP policy and report information to Web Console (Part 1); r=dveditz,msucan,jwalker
This commit is contained in:
parent
2561b4b1e6
commit
344f390f55
@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
@ -20,17 +21,16 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
|
||||
// Module stuff
|
||||
var EXPORTED_SYMBOLS = ["CSPRep", "CSPSourceList", "CSPSource", "CSPHost",
|
||||
"CSPWarning", "CSPError", "CSPdebug",
|
||||
"CSPViolationReportListener", "CSPLocalizer"];
|
||||
"CSPdebug", "CSPViolationReportListener", "CSPLocalizer"];
|
||||
|
||||
var STRINGS_URI = "chrome://global/locale/security/csp.properties";
|
||||
|
||||
// these are not exported
|
||||
var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
var gETLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
|
||||
.getService(Components.interfaces.nsIEffectiveTLDService);
|
||||
.getService(Ci.nsIEffectiveTLDService);
|
||||
|
||||
// These regexps represent the concrete syntax on the w3 spec as of 7-5-2012
|
||||
// scheme = <scheme production from RFC 3986>
|
||||
@ -76,58 +76,30 @@ var gPrefObserver = {
|
||||
|
||||
_initialize: function() {
|
||||
var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefService);
|
||||
.getService(Ci.nsIPrefService);
|
||||
this._branch = prefSvc.getBranch("security.csp.");
|
||||
this._branch.addObserver("", this, false);
|
||||
this._debugEnabled = this._branch.getBoolPref("debug");
|
||||
},
|
||||
|
||||
unregister: function() {
|
||||
if(!this._branch) return;
|
||||
if (!this._branch) return;
|
||||
this._branch.removeObserver("", this);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if(aTopic != "nsPref:changed") return;
|
||||
if(aData === "debug")
|
||||
if (aTopic != "nsPref:changed") return;
|
||||
if (aData === "debug")
|
||||
this._debugEnabled = this._branch.getBoolPref("debug");
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
function CSPWarning(aMsg, aWindowID, aSource, aScriptSample, aLineNum) {
|
||||
var textMessage = 'CSP WARN: ' + aMsg + "\n";
|
||||
|
||||
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptError);
|
||||
consoleMsg.initWithWindowID(textMessage, aSource, aScriptSample, aLineNum, 0,
|
||||
Components.interfaces.nsIScriptError.warningFlag,
|
||||
"Content Security Policy", aWindowID);
|
||||
Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Components.interfaces.nsIConsoleService)
|
||||
.logMessage(consoleMsg);
|
||||
}
|
||||
|
||||
function CSPError(aMsg, aWindowID) {
|
||||
var textMessage = 'CSP ERROR: ' + aMsg + "\n";
|
||||
|
||||
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptError);
|
||||
consoleMsg.initWithWindowID(textMessage, null, null, 0, 0,
|
||||
Components.interfaces.nsIScriptError.errorFlag,
|
||||
"Content Security Policy", aWindowID);
|
||||
Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Components.interfaces.nsIConsoleService)
|
||||
.logMessage(consoleMsg);
|
||||
}
|
||||
|
||||
function CSPdebug(aMsg) {
|
||||
if (!gPrefObserver.debugEnabled) return;
|
||||
|
||||
aMsg = 'CSP debug: ' + aMsg + "\n";
|
||||
Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Components.interfaces.nsIConsoleService)
|
||||
.getService(Ci.nsIConsoleService)
|
||||
.logStringMessage(aMsg);
|
||||
}
|
||||
|
||||
@ -138,16 +110,16 @@ function CSPPolicyURIListener(policyURI, docRequest, csp) {
|
||||
this._csp = csp; // parent document's CSP
|
||||
this._policy = ""; // contents fetched from policyURI
|
||||
this._wrapper = null; // nsIScriptableInputStream
|
||||
this._docURI = docRequest.QueryInterface(Components.interfaces.nsIChannel)
|
||||
this._docURI = docRequest.QueryInterface(Ci.nsIChannel)
|
||||
.URI; // parent document URI (to be used as 'self')
|
||||
}
|
||||
|
||||
CSPPolicyURIListener.prototype = {
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Components.interfaces.nsIStreamListener) ||
|
||||
iid.equals(Components.interfaces.nsIRequestObserver) ||
|
||||
iid.equals(Components.interfaces.nsISupports))
|
||||
if (iid.equals(Ci.nsIStreamListener) ||
|
||||
iid.equals(Ci.nsIRequestObserver) ||
|
||||
iid.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
@ -159,7 +131,7 @@ CSPPolicyURIListener.prototype = {
|
||||
function(request, context, inputStream, offset, count) {
|
||||
if (this._wrapper == null) {
|
||||
this._wrapper = Components.classes["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptableInputStream);
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
this._wrapper.init(inputStream);
|
||||
}
|
||||
// store the remote policy as it becomes available
|
||||
@ -241,9 +213,10 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
var UD = CSPRep.URI_DIRECTIVES;
|
||||
var aCSPR = new CSPRep();
|
||||
aCSPR._originalText = aStr;
|
||||
aCSPR._innerWindowID = innerWindowFromRequest(docRequest);
|
||||
|
||||
var selfUri = null;
|
||||
if (self instanceof Components.interfaces.nsIURI)
|
||||
if (self instanceof Ci.nsIURI)
|
||||
selfUri = self.clone();
|
||||
|
||||
var dirs = aStr.split(";");
|
||||
@ -258,7 +231,8 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
|
||||
if (aCSPR._directives.hasOwnProperty(dirname)) {
|
||||
// Check for (most) duplicate directives
|
||||
CSPError(CSPLocalizer.getFormatStr("duplicateDirective", [dirname]));
|
||||
cspError(aCSPR, CSPLocalizer.getFormatStr("duplicateDirective",
|
||||
[dirname]));
|
||||
CSPdebug("Skipping duplicate directive: \"" + dir + "\"");
|
||||
continue directive;
|
||||
}
|
||||
@ -267,7 +241,8 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
if (dirname === CSPRep.OPTIONS_DIRECTIVE) {
|
||||
if (aCSPR._allowInlineScripts || aCSPR._allowEval) {
|
||||
// Check for duplicate options directives
|
||||
CSPError(CSPLocalizer.getFormatStr("duplicateDirective", [dirname]));
|
||||
cspError(aCSPR, CSPLocalizer.getFormatStr("duplicateDirective",
|
||||
[dirname]));
|
||||
CSPdebug("Skipping duplicate directive: \"" + dir + "\"");
|
||||
continue directive;
|
||||
}
|
||||
@ -280,7 +255,8 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
else if (opt === "eval-script")
|
||||
aCSPR._allowEval = true;
|
||||
else
|
||||
CSPWarning(CSPLocalizer.getFormatStr("doNotUnderstandOption", [opt]));
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("doNotUnderstandOption",
|
||||
[opt]));
|
||||
}
|
||||
continue directive;
|
||||
}
|
||||
@ -289,14 +265,15 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
// parse "allow" as equivalent to "default-src", at least until the spec
|
||||
// stabilizes, at which time we can stop parsing "allow"
|
||||
if (dirname === CSPRep.ALLOW_DIRECTIVE) {
|
||||
CSPWarning(CSPLocalizer.getStr("allowDirectiveDeprecated"));
|
||||
cspWarn(aCSPR, CSPLocalizer.getStr("allowDirectiveDeprecated"));
|
||||
if (aCSPR._directives.hasOwnProperty(SD.DEFAULT_SRC)) {
|
||||
// Check for duplicate default-src and allow directives
|
||||
CSPError(CSPLocalizer.getFormatStr("duplicateDirective", [dirname]));
|
||||
cspError(aCSPR, CSPLocalizer.getFormatStr("duplicateDirective",
|
||||
[dirname]));
|
||||
CSPdebug("Skipping duplicate directive: \"" + dir + "\"");
|
||||
continue directive;
|
||||
}
|
||||
var dv = CSPSourceList.fromString(dirvalue, self, true);
|
||||
var dv = CSPSourceList.fromString(dirvalue, aCSPR, self, true);
|
||||
if (dv) {
|
||||
aCSPR._directives[SD.DEFAULT_SRC] = dv;
|
||||
continue directive;
|
||||
@ -307,7 +284,7 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
for each(var sdi in SD) {
|
||||
if (dirname === sdi) {
|
||||
// process dirs, and enforce that 'self' is defined.
|
||||
var dv = CSPSourceList.fromString(dirvalue, self, true);
|
||||
var dv = CSPSourceList.fromString(dirvalue, aCSPR, self, true);
|
||||
if (dv) {
|
||||
aCSPR._directives[sdi] = dv;
|
||||
continue directive;
|
||||
@ -340,18 +317,19 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
if (self) {
|
||||
if (gETLDService.getBaseDomain(uri) !==
|
||||
gETLDService.getBaseDomain(selfUri)) {
|
||||
CSPWarning(CSPLocalizer.getFormatStr("notETLDPlus1",
|
||||
[gETLDService.getBaseDomain(uri)]));
|
||||
cspWarn(aCSPR,
|
||||
CSPLocalizer.getFormatStr("notETLDPlus1",
|
||||
[gETLDService.getBaseDomain(uri)]));
|
||||
continue;
|
||||
}
|
||||
if (!uri.schemeIs(selfUri.scheme)) {
|
||||
CSPWarning(CSPLocalizer.getFormatStr("notSameScheme",
|
||||
[uri.asciiSpec]));
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("notSameScheme",
|
||||
[uri.asciiSpec]));
|
||||
continue;
|
||||
}
|
||||
if (uri.port && uri.port !== selfUri.port) {
|
||||
CSPWarning(CSPLocalizer.getFormatStr("notSamePort",
|
||||
[uri.asciiSpec]));
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("notSamePort",
|
||||
[uri.asciiSpec]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -360,15 +338,16 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
case Components.results.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS:
|
||||
case Components.results.NS_ERROR_HOST_IS_IP_ADDRESS:
|
||||
if (uri.host !== selfUri.host) {
|
||||
CSPWarning(CSPLocalizer.getFormatStr("pageCannotSendReportsTo",
|
||||
[selfUri.host, uri.host]));
|
||||
cspWarn(aCSPR,
|
||||
CSPLocalizer.getFormatStr("pageCannotSendReportsTo",
|
||||
[selfUri.host, uri.host]));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CSPWarning(CSPLocalizer.getFormatStr("couldNotParseReportURI",
|
||||
[uriStrings[i]]));
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("couldNotParseReportURI",
|
||||
[uriStrings[i]]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -383,13 +362,13 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
if (dirname === UD.POLICY_URI) {
|
||||
// POLICY_URI can only be alone
|
||||
if (aCSPR._directives.length > 0 || dirs.length > 1) {
|
||||
CSPError(CSPLocalizer.getStr("policyURINotAlone"));
|
||||
cspError(aCSPR, CSPLocalizer.getStr("policyURINotAlone"));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
// if we were called without a reference to the parent document request
|
||||
// we won't be able to suspend it while we fetch the policy -> fail closed
|
||||
if (!docRequest || !csp) {
|
||||
CSPError(CSPLocalizer.getStr("noParentRequest"));
|
||||
cspError(aCSPR, CSPLocalizer.getStr("noParentRequest"));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
|
||||
@ -397,22 +376,26 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
try {
|
||||
uri = gIoService.newURI(dirvalue, null, selfUri);
|
||||
} catch(e) {
|
||||
CSPError(CSPLocalizer.getFormatStr("policyURIParseError", [dirvalue]));
|
||||
cspError(aCSPR, CSPLocalizer.getFormatStr("policyURIParseError",
|
||||
[dirvalue]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
|
||||
// Verify that policy URI comes from the same origin
|
||||
if (selfUri) {
|
||||
if (selfUri.host !== uri.host){
|
||||
CSPError(CSPLocalizer.getFormatStr("nonMatchingHost", [uri.host]));
|
||||
if (selfUri.host !== uri.host) {
|
||||
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingHost",
|
||||
[uri.host]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
if (selfUri.port !== uri.port){
|
||||
CSPError(CSPLocalizer.getFormatStr("nonMatchingPort", [uri.port.toString()]));
|
||||
if (selfUri.port !== uri.port) {
|
||||
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingPort",
|
||||
[uri.port.toString()]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
if (selfUri.scheme !== uri.scheme){
|
||||
CSPError(CSPLocalizer.getFormatStr("nonMatchingScheme", [uri.scheme]));
|
||||
if (selfUri.scheme !== uri.scheme) {
|
||||
cspError(aCSPR, CSPLocalizer.getFormatStr("nonMatchingScheme",
|
||||
[uri.scheme]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
}
|
||||
@ -423,13 +406,14 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
var chan = gIoService.newChannel(uri.asciiSpec, null, null);
|
||||
// make request anonymous (no cookies, etc.) so the request for the
|
||||
// policy-uri can't be abused for CSRF
|
||||
chan.loadFlags |= Components.interfaces.nsIChannel.LOAD_ANONYMOUS;
|
||||
chan.loadFlags |= Ci.nsIChannel.LOAD_ANONYMOUS;
|
||||
chan.asyncOpen(new CSPPolicyURIListener(uri, docRequest, csp), null);
|
||||
}
|
||||
catch (e) {
|
||||
// resume the document request and apply most restrictive policy
|
||||
docRequest.resume();
|
||||
CSPError(CSPLocalizer.getFormatStr("errorFetchingPolicy", [e.toString()]));
|
||||
cspError(aCSPR, CSPLocalizer.getFormatStr("errorFetchingPolicy",
|
||||
[e.toString()]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
|
||||
@ -439,7 +423,8 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
||||
}
|
||||
|
||||
// UNIDENTIFIED DIRECTIVE /////////////////////////////////////////////
|
||||
CSPWarning(CSPLocalizer.getFormatStr("couldNotProcessUnknownDirective", [dirname]));
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("couldNotProcessUnknownDirective",
|
||||
[dirname]));
|
||||
|
||||
} // end directive: loop
|
||||
|
||||
@ -511,7 +496,7 @@ CSPRep.prototype = {
|
||||
// GLOBALLY ALLOW "about:" SCHEME
|
||||
if (aURI instanceof String && aURI.substring(0,6) === "about:")
|
||||
return true;
|
||||
if (aURI instanceof Components.interfaces.nsIURI && aURI.scheme === "about")
|
||||
if (aURI instanceof Ci.nsIURI && aURI.scheme === "about")
|
||||
return true;
|
||||
|
||||
// make sure the context is valid
|
||||
@ -563,6 +548,9 @@ CSPRep.prototype = {
|
||||
|
||||
newRep._allowInlineScripts = this.allowsInlineScripts
|
||||
&& aCSPRep.allowsInlineScripts;
|
||||
|
||||
newRep._innerWindowID = this._innerWindowID ?
|
||||
this._innerWindowID : aCSPRep._innerWindowID;
|
||||
|
||||
return newRep;
|
||||
},
|
||||
@ -578,7 +566,7 @@ CSPRep.prototype = {
|
||||
var SD = CSPRep.SRC_DIRECTIVES;
|
||||
var defaultSrcDir = this._directives[SD.DEFAULT_SRC];
|
||||
if (!defaultSrcDir) {
|
||||
CSPWarning(CSPLocalizer.getStr("allowOrDefaultSrcRequired"));
|
||||
this.warn(CSPLocalizer.getStr("allowOrDefaultSrcRequired"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -589,7 +577,7 @@ CSPRep.prototype = {
|
||||
// implicit directive, make explicit.
|
||||
// All but frame-ancestors directive inherit from 'allow' (bug 555068)
|
||||
if (dirv === SD.FRAME_ANCESTORS)
|
||||
this._directives[dirv] = CSPSourceList.fromString("*");
|
||||
this._directives[dirv] = CSPSourceList.fromString("*",this);
|
||||
else
|
||||
this._directives[dirv] = defaultSrcDir.clone();
|
||||
this._directives[dirv]._isImplicit = true;
|
||||
@ -613,6 +601,62 @@ CSPRep.prototype = {
|
||||
get allowsInlineScripts () {
|
||||
return this._allowInlineScripts;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a warning message to the error console and web developer console.
|
||||
* @param aMsg
|
||||
* The message to send
|
||||
* @param aSource (optional)
|
||||
* The URL of the file in which the error occurred
|
||||
* @param aScriptLine (optional)
|
||||
* The line in the source file which the error occurred
|
||||
* @param aLineNum (optional)
|
||||
* The number of the line where the error occurred
|
||||
*/
|
||||
warn:
|
||||
function cspd_warn(aMsg, aSource, aScriptLine, aLineNum) {
|
||||
var textMessage = 'CSP WARN: ' + aMsg + "\n";
|
||||
|
||||
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
|
||||
.createInstance(Ci.nsIScriptError);
|
||||
if (this._innerWindowID) {
|
||||
consoleMsg.initWithWindowID(textMessage, aSource, aScriptLine, aLineNum,
|
||||
0, Ci.nsIScriptError.warningFlag,
|
||||
"Content Security Policy",
|
||||
this._innerWindowID);
|
||||
} else {
|
||||
consoleMsg.init(textMessage, aSource, aScriptLine, aLineNum, 0,
|
||||
Ci.nsIScriptError.warningFlag,
|
||||
"Content Security Policy");
|
||||
}
|
||||
Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService).logMessage(consoleMsg);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends an error message to the error console and web developer console.
|
||||
* @param aMsg
|
||||
* The message to send
|
||||
*/
|
||||
error:
|
||||
function cspsd_error(aMsg) {
|
||||
var textMessage = 'CSP ERROR: ' + aMsg + "\n";
|
||||
|
||||
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
|
||||
.createInstance(Ci.nsIScriptError);
|
||||
if (this._innerWindowID) {
|
||||
consoleMsg.initWithWindowID(textMessage, null, null, 0, 0,
|
||||
Ci.nsIScriptError.errorFlag,
|
||||
"Content Security Policy",
|
||||
this._innerWindowID);
|
||||
}
|
||||
else {
|
||||
consoleMsg.init(textMessage, null, null, 0, 0,
|
||||
Ci.nsIScriptError.errorFlag, "Content Security Policy");
|
||||
}
|
||||
Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService).logMessage(consoleMsg);
|
||||
},
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -633,6 +677,9 @@ function CSPSourceList() {
|
||||
*
|
||||
* @param aStr
|
||||
* string rep of a CSP Source List
|
||||
* @param aCSPRep
|
||||
* the CSPRep to which this souce list belongs. If null, CSP errors and
|
||||
* warnings will not be sent to the web console.
|
||||
* @param self (optional)
|
||||
* URI or CSPSource representing the "self" source
|
||||
* @param enforceSelfChecks (optional)
|
||||
@ -641,39 +688,42 @@ function CSPSourceList() {
|
||||
* @returns
|
||||
* an instance of CSPSourceList
|
||||
*/
|
||||
CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
CSPSourceList.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
|
||||
// source-list = *WSP [ source-expression *( 1*WSP source-expression ) *WSP ]
|
||||
// / *WSP "'none'" *WSP
|
||||
|
||||
/* If self parameter is passed, convert to CSPSource,
|
||||
unless it is already a CSPSource. */
|
||||
if(self && !(self instanceof CSPSource)) {
|
||||
self = CSPSource.create(self);
|
||||
if (self && !(self instanceof CSPSource)) {
|
||||
self = CSPSource.create(self, aCSPRep);
|
||||
}
|
||||
|
||||
var slObj = new CSPSourceList();
|
||||
slObj._CSPRep = aCSPRep;
|
||||
aStr = aStr.trim();
|
||||
// w3 specifies case insensitive equality
|
||||
if (aStr.toUpperCase() === "'NONE'"){
|
||||
if (aStr.toUpperCase() === "'NONE'") {
|
||||
slObj._permitAllSources = false;
|
||||
return slObj;
|
||||
}
|
||||
|
||||
var tokens = aStr.split(/\s+/);
|
||||
for (var i in tokens) {
|
||||
if (!R_SOURCEEXP.test(tokens[i])){
|
||||
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
|
||||
[tokens[i]]));
|
||||
if (!R_SOURCEEXP.test(tokens[i])) {
|
||||
cspWarn(aCSPRep,
|
||||
CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
|
||||
[tokens[i]]));
|
||||
continue;
|
||||
}
|
||||
var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
|
||||
var src = CSPSource.create(tokens[i], aCSPRep, self, enforceSelfChecks);
|
||||
if (!src) {
|
||||
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
|
||||
[tokens[i]]));
|
||||
cspWarn(aCSPRep,
|
||||
CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
|
||||
[tokens[i]]));
|
||||
continue;
|
||||
}
|
||||
// if a source is a *, then we can permit all sources
|
||||
if (src.permitAll){
|
||||
if (src.permitAll) {
|
||||
slObj._permitAllSources = true;
|
||||
return slObj;
|
||||
} else {
|
||||
@ -758,6 +808,7 @@ CSPSourceList.prototype = {
|
||||
function() {
|
||||
var aSL = new CSPSourceList();
|
||||
aSL._permitAllSources = this._permitAllSources;
|
||||
aSL._CSPRep = this._CSPRep;
|
||||
for (var i in this._sources) {
|
||||
aSL._sources[i] = this._sources[i].clone();
|
||||
}
|
||||
@ -800,7 +851,7 @@ CSPSourceList.prototype = {
|
||||
if (!that) return this.clone();
|
||||
|
||||
if (this.isNone() || that.isNone())
|
||||
newCSPSrcList = CSPSourceList.fromString("'none'");
|
||||
newCSPSrcList = CSPSourceList.fromString("'none'", this._CSPRep);
|
||||
|
||||
if (this.isAll()) newCSPSrcList = that.clone();
|
||||
if (that.isAll()) newCSPSrcList = this.clone();
|
||||
@ -837,6 +888,9 @@ CSPSourceList.prototype = {
|
||||
// if either was explicit, so is this.
|
||||
newCSPSrcList._isImplicit = this._isImplicit && that._isImplicit;
|
||||
|
||||
if ((!newCSPSrcList._CSPRep) && that._CSPRep) {
|
||||
newCSPSrcList._CSPRep = that._CSPRep;
|
||||
}
|
||||
return newCSPSrcList;
|
||||
}
|
||||
}
|
||||
@ -865,6 +919,9 @@ function CSPSource() {
|
||||
* - CSPSource (clone)
|
||||
* @param aData
|
||||
* string, nsURI, or CSPSource
|
||||
* @param aCSPRep
|
||||
* The CSPRep this source belongs to. If null, CSP errors and warnings
|
||||
* will not be sent to the web console.
|
||||
* @param self (optional)
|
||||
* if present, string, URI, or CSPSource representing the "self" resource
|
||||
* @param enforceSelfChecks (optional)
|
||||
@ -873,12 +930,12 @@ function CSPSource() {
|
||||
* @returns
|
||||
* an instance of CSPSource
|
||||
*/
|
||||
CSPSource.create = function(aData, self, enforceSelfChecks) {
|
||||
CSPSource.create = function(aData, aCSPRep, self, enforceSelfChecks) {
|
||||
if (typeof aData === 'string')
|
||||
return CSPSource.fromString(aData, self, enforceSelfChecks);
|
||||
return CSPSource.fromString(aData, aCSPRep, self, enforceSelfChecks);
|
||||
|
||||
if (aData instanceof Components.interfaces.nsIURI)
|
||||
return CSPSource.fromURI(aData, self, enforceSelfChecks);
|
||||
if (aData instanceof Ci.nsIURI)
|
||||
return CSPSource.fromURI(aData, aCSPRep, self, enforceSelfChecks);
|
||||
|
||||
if (aData instanceof CSPSource) {
|
||||
var ns = aData.clone();
|
||||
@ -896,6 +953,9 @@ CSPSource.create = function(aData, self, enforceSelfChecks) {
|
||||
*
|
||||
* @param aURI
|
||||
* nsIURI rep of a URI
|
||||
* @param aCSPRep
|
||||
* The policy this source belongs to. If null, CSP errors and warnings
|
||||
* will not be sent to the web console.
|
||||
* @param self (optional)
|
||||
* string or CSPSource representing the "self" source
|
||||
* @param enforceSelfChecks (optional)
|
||||
@ -904,23 +964,24 @@ CSPSource.create = function(aData, self, enforceSelfChecks) {
|
||||
* @returns
|
||||
* an instance of CSPSource
|
||||
*/
|
||||
CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
|
||||
if (!(aURI instanceof Components.interfaces.nsIURI)){
|
||||
CSPError(CSPLocalizer.getStr("cspSourceNotURI"));
|
||||
CSPSource.fromURI = function(aURI, aCSPRep, self, enforceSelfChecks) {
|
||||
if (!(aURI instanceof Ci.nsIURI)) {
|
||||
cspError(aCSPRep, CSPLocalizer.getStr("cspSourceNotURI"));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!self && enforceSelfChecks) {
|
||||
CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
|
||||
cspError(aCSPRep, CSPLocalizer.getStr("selfDataNotProvided"));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (self && !(self instanceof CSPSource)) {
|
||||
self = CSPSource.create(self, undefined, false);
|
||||
self = CSPSource.create(self, aCSPRep, undefined, false);
|
||||
}
|
||||
|
||||
var sObj = new CSPSource();
|
||||
sObj._self = self;
|
||||
sObj._CSPRep = aCSPRep;
|
||||
|
||||
// PARSE
|
||||
// If 'self' is undefined, then use default port for scheme if there is one.
|
||||
@ -930,7 +991,8 @@ CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
|
||||
sObj._scheme = aURI.scheme;
|
||||
} catch(e) {
|
||||
sObj._scheme = undefined;
|
||||
CSPError(CSPLocalizer.getFormatStr("uriWithoutScheme", [aURI.asciiSpec]));
|
||||
cspError(aCSPRep, CSPLocalizer.getFormatStr("uriWithoutScheme",
|
||||
[aURI.asciiSpec]));
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -973,6 +1035,8 @@ CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
|
||||
*
|
||||
* @param aStr
|
||||
* string rep of a CSP Source
|
||||
* @param aCSPRep
|
||||
* the CSPRep this CSPSource belongs to
|
||||
* @param self (optional)
|
||||
* string, URI, or CSPSource representing the "self" source
|
||||
* @param enforceSelfChecks (optional)
|
||||
@ -981,35 +1045,37 @@ CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
|
||||
* @returns
|
||||
* an instance of CSPSource
|
||||
*/
|
||||
CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
|
||||
if (!aStr)
|
||||
return null;
|
||||
|
||||
if (!(typeof aStr === 'string')) {
|
||||
CSPError(CSPLocalizer.getStr("argumentIsNotString"));
|
||||
cspError(aCSPRep, CSPLocalizer.getStr("argumentIsNotString"));
|
||||
return null;
|
||||
}
|
||||
|
||||
var sObj = new CSPSource();
|
||||
sObj._self = self;
|
||||
sObj._CSPRep = aCSPRep;
|
||||
|
||||
|
||||
// if equal, return does match
|
||||
if (aStr === "*"){
|
||||
if (aStr === "*") {
|
||||
sObj._permitAll = true;
|
||||
return sObj;
|
||||
}
|
||||
|
||||
if (!self && enforceSelfChecks) {
|
||||
CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
|
||||
cspError(aCSPRep, CSPLocalizer.getStr("selfDataNotProvided"));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (self && !(self instanceof CSPSource)) {
|
||||
self = CSPSource.create(self, undefined, false);
|
||||
self = CSPSource.create(self, aCSPRep, undefined, false);
|
||||
}
|
||||
|
||||
// check for scheme-source match
|
||||
if (R_SCHEMESRC.test(aStr)){
|
||||
if (R_SCHEMESRC.test(aStr)) {
|
||||
var schemeSrcMatch = R_GETSCHEME.exec(aStr);
|
||||
sObj._scheme = schemeSrcMatch[0];
|
||||
if (!sObj._host) sObj._host = CSPHost.fromString("*");
|
||||
@ -1031,8 +1097,9 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
|
||||
// get array of matches to the R_HOST regular expression
|
||||
var hostMatch = R_HOST.exec(aStr);
|
||||
if (!hostMatch){
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
|
||||
if (!hostMatch) {
|
||||
cspError(aCSPRep, CSPLocalizer.getFormatStr("couldntParseInvalidSource",
|
||||
[aStr]));
|
||||
return null;
|
||||
}
|
||||
// host regex gets scheme, so remove scheme from aStr. Add 3 for '://'
|
||||
@ -1044,7 +1111,9 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
// gets the default port for the given scheme
|
||||
defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
|
||||
if (!defPort) {
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
|
||||
cspError(aCSPRep,
|
||||
CSPLocalizer.getFormatStr("couldntParseInvalidSource",
|
||||
[aStr]));
|
||||
return null;
|
||||
}
|
||||
sObj._port = defPort;
|
||||
@ -1057,16 +1126,17 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
}
|
||||
|
||||
// check for 'self' (case insensitive)
|
||||
if (aStr.toUpperCase() === "'SELF'"){
|
||||
if (!self){
|
||||
CSPError(CSPLocalizer.getStr("selfKeywordNoSelfData"));
|
||||
if (aStr.toUpperCase() === "'SELF'") {
|
||||
if (!self) {
|
||||
cspError(aCSPRep, CSPLocalizer.getStr("selfKeywordNoSelfData"));
|
||||
return null;
|
||||
}
|
||||
sObj._self = self.clone();
|
||||
sObj._isSelf = true;
|
||||
return sObj;
|
||||
}
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
|
||||
cspError(aCSPRep, CSPLocalizer.getFormatStr("couldntParseInvalidSource",
|
||||
[aStr]));
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -1156,6 +1226,7 @@ CSPSource.prototype = {
|
||||
aClone._port = this._port;
|
||||
aClone._host = this._host ? this._host.clone() : undefined;
|
||||
aClone._isSelf = this._isSelf;
|
||||
aClone._CSPRep = this._CSPRep;
|
||||
return aClone;
|
||||
},
|
||||
|
||||
@ -1171,7 +1242,7 @@ CSPSource.prototype = {
|
||||
if (!aSource) return false;
|
||||
|
||||
if (!(aSource instanceof CSPSource))
|
||||
return this.permits(CSPSource.create(aSource));
|
||||
return this.permits(CSPSource.create(aSource, this._CSPRep));
|
||||
|
||||
// verify scheme
|
||||
if (this.scheme != aSource.scheme)
|
||||
@ -1225,7 +1296,9 @@ CSPSource.prototype = {
|
||||
else if (that.port === this.port)
|
||||
newSource._port = this.port;
|
||||
else {
|
||||
CSPError(CSPLocalizer.getFormatStr("notIntersectPort", [this.toString(), that.toString()]));
|
||||
let msg = CSPLocalizer.getFormatStr("notIntersectPort",
|
||||
[this.toString(), that.toString()]);
|
||||
cspError(this._CSPRep, msg);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -1241,7 +1314,9 @@ CSPSource.prototype = {
|
||||
else if (that.scheme === this.scheme)
|
||||
newSource._scheme = this.scheme;
|
||||
else {
|
||||
CSPError(CSPLocalizer.getFormatStr("notIntersectScheme", [this.toString(), that.toString()]));
|
||||
var msg = CSPLocalizer.getFormatStr("notIntersectScheme",
|
||||
[this.toString(), that.toString()]);
|
||||
cspError(this._CSPRep, msg);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -1257,13 +1332,19 @@ CSPSource.prototype = {
|
||||
if (this.host && that.host) {
|
||||
newSource._host = this.host.intersectWith(that.host);
|
||||
} else if (this.host) {
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [that.toString()]));
|
||||
let msg = CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost",
|
||||
[that.toString()]);
|
||||
cspError(this._CSPRep, msg);
|
||||
newSource._host = this.host.clone();
|
||||
} else if (that.host) {
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [this.toString()]));
|
||||
let msg = CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost",
|
||||
[this.toString()]);
|
||||
cspError(this._CSPRep, msg);
|
||||
newSource._host = that.host.clone();
|
||||
} else {
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourcesWithUndefinedHosts", [this.toString(), that.toString()]));
|
||||
let msg = CSPLocalizer.getFormatStr("intersectingSourcesWithUndefinedHosts",
|
||||
[this.toString(), that.toString()]);
|
||||
cspError(this._CSPRep, msg);
|
||||
newSource._host = CSPHost.fromString("*");
|
||||
}
|
||||
|
||||
@ -1482,7 +1563,7 @@ CSPViolationReportListener.prototype = {
|
||||
_reportURI: null,
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if(iid.equals(Ci.nsIStreamListener) ||
|
||||
if (iid.equals(Ci.nsIStreamListener) ||
|
||||
iid.equals(Ci.nsIRequestObserver) ||
|
||||
iid.equals(Ci.nsISupports))
|
||||
return this;
|
||||
@ -1508,6 +1589,52 @@ CSPViolationReportListener.prototype = {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
function innerWindowFromRequest(docRequest) {
|
||||
let win = null;
|
||||
let loadContext = null;
|
||||
|
||||
try {
|
||||
loadContext = docRequest.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
} catch (ex) {
|
||||
try {
|
||||
loadContext = docRequest.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (loadContext) {
|
||||
win = loadContext.associatedWindow;
|
||||
}
|
||||
if (win) {
|
||||
try {
|
||||
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
return winUtils.currentInnerWindowID;
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function cspError(aCSPRep, aMessage) {
|
||||
if (aCSPRep) {
|
||||
aCSPRep.error(aMessage);
|
||||
} else {
|
||||
(new CSPRep()).error(aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function cspWarn(aCSPRep, aMessage) {
|
||||
if (aCSPRep) {
|
||||
aCSPRep.warn(aMessage);
|
||||
} else {
|
||||
(new CSPRep()).warn(aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CSPLocalizer = {
|
||||
/**
|
||||
* Retrieve a localized string.
|
||||
|
@ -104,34 +104,6 @@ ContentSecurityPolicy.prototype = {
|
||||
return this._reportOnlyMode || this._policy.allowsEvalInScripts;
|
||||
},
|
||||
|
||||
get innerWindowID() {
|
||||
let win = null;
|
||||
let loadContext = null;
|
||||
|
||||
try {
|
||||
loadContext = this._docRequest
|
||||
.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
} catch (ex) {
|
||||
try {
|
||||
loadContext = this._docRequest.loadGroup
|
||||
.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
} catch (ex) {
|
||||
}
|
||||
}
|
||||
|
||||
if (loadContext) {
|
||||
win = loadContext.associatedWindow;
|
||||
}
|
||||
if (win) {
|
||||
try {
|
||||
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
return winUtils.currentInnerWindowID;
|
||||
} catch (ex) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Log policy violation on the Error Console and send a report if a report-uri
|
||||
* is present in the policy
|
||||
@ -302,16 +274,15 @@ ContentSecurityPolicy.prototype = {
|
||||
CSPdebug("Constructed violation report:\n" + reportString);
|
||||
|
||||
var violationMessage = null;
|
||||
if(blockedUri["asciiSpec"]){
|
||||
if (blockedUri["asciiSpec"]) {
|
||||
violationMessage = CSPLocalizer.getFormatStr("directiveViolatedWithURI", [violatedDirective, blockedUri.asciiSpec]);
|
||||
} else {
|
||||
violationMessage = CSPLocalizer.getFormatStr("directiveViolated", [violatedDirective]);
|
||||
}
|
||||
CSPWarning(violationMessage,
|
||||
this.innerWindowID,
|
||||
(aSourceFile) ? aSourceFile : null,
|
||||
(aScriptSample) ? decodeURIComponent(aScriptSample) : null,
|
||||
(aLineNum) ? aLineNum : null);
|
||||
this._policy.warn(violationMessage,
|
||||
(aSourceFile) ? aSourceFile : null,
|
||||
(aScriptSample) ? decodeURIComponent(aScriptSample) : null,
|
||||
(aLineNum) ? aLineNum : null);
|
||||
|
||||
// For each URI in the report list, send out a report.
|
||||
// We make the assumption that all of the URIs are absolute URIs; this
|
||||
@ -323,7 +294,7 @@ ContentSecurityPolicy.prototype = {
|
||||
|
||||
try {
|
||||
var chan = Services.io.newChannel(uris[i], null, null);
|
||||
if(!chan) {
|
||||
if (!chan) {
|
||||
CSPdebug("Error creating channel for " + uris[i]);
|
||||
continue;
|
||||
}
|
||||
@ -338,7 +309,7 @@ ContentSecurityPolicy.prototype = {
|
||||
|
||||
// we need to set an nsIChannelEventSink on the channel object
|
||||
// so we can tell it to not follow redirects when posting the reports
|
||||
chan.notificationCallbacks = new CSPReportRedirectSink();
|
||||
chan.notificationCallbacks = new CSPReportRedirectSink(this._policy);
|
||||
|
||||
chan.QueryInterface(Ci.nsIUploadChannel)
|
||||
.setUploadStream(content, "application/json", content.available());
|
||||
@ -369,8 +340,8 @@ ContentSecurityPolicy.prototype = {
|
||||
} catch(e) {
|
||||
// it's possible that the URI was invalid, just log a
|
||||
// warning and skip over that.
|
||||
CSPWarning(CSPLocalizer.getFormatStr("triedToSendReport", [uris[i]]), this.innerWindowID);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("errorWas", [e.toString()]), this.innerWindowID);
|
||||
this._policy.warn(CSPLocalizer.getFormatStr("triedToSendReport", [uris[i]]));
|
||||
this._policy.warn(CSPLocalizer.getFormatStr("errorWas", [e.toString()]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -552,7 +523,8 @@ ContentSecurityPolicy.prototype = {
|
||||
// The POST of the violation report (if it happens) should not follow
|
||||
// redirects, per the spec. hence, we implement an nsIChannelEventSink
|
||||
// with an object so we can tell XHR to abort if a redirect happens.
|
||||
function CSPReportRedirectSink() {
|
||||
function CSPReportRedirectSink(policy) {
|
||||
this._policy = policy;
|
||||
}
|
||||
|
||||
CSPReportRedirectSink.prototype = {
|
||||
@ -575,7 +547,7 @@ CSPReportRedirectSink.prototype = {
|
||||
// nsIChannelEventSink
|
||||
asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel,
|
||||
flags, callback) {
|
||||
CSPWarning(CSPLocalizer.getFormatStr("reportPostRedirect", [oldChannel.URI.asciiSpec]));
|
||||
this._policy.warn(CSPLocalizer.getFormatStr("reportPostRedirect", [oldChannel.URI.asciiSpec]));
|
||||
|
||||
// cancel the old channel so XHR failure callback happens
|
||||
oldChannel.cancel(Cr.NS_ERROR_ABORT);
|
||||
|
@ -159,29 +159,29 @@ test(
|
||||
function test_CSPSource_fromString() {
|
||||
// can't do these tests because "self" is not defined.
|
||||
//"basic source should not be null.");
|
||||
do_check_neq(null, CSPSource.fromString("a.com", "http://abc.com"));
|
||||
do_check_neq(null, CSPSource.fromString("a.com", undefined, "http://abc.com"));
|
||||
|
||||
//"ldh characters should all work for host.");
|
||||
do_check_neq(null, CSPSource.fromString("a2-c.com", "https://a.com"));
|
||||
do_check_neq(null, CSPSource.fromString("a2-c.com", undefined, "https://a.com"));
|
||||
|
||||
//"wildcard should work in first token for host.");
|
||||
do_check_neq(null, CSPSource.fromString("*.a.com", "http://abc.com"));
|
||||
do_check_neq(null, CSPSource.fromString("*.a.com", undefined, "http://abc.com"));
|
||||
|
||||
//print(" --- Ignore the following two errors if they print ---");
|
||||
//"wildcard should not work in non-first token for host.");
|
||||
do_check_eq(null, CSPSource.fromString("x.*.a.com", "http://a.com"));
|
||||
do_check_eq(null, CSPSource.fromString("x.*.a.com", undefined, "http://a.com"));
|
||||
|
||||
//"funny characters (#) should not work for host.");
|
||||
do_check_eq(null, CSPSource.fromString("a#2-c.com", "http://a.com"));
|
||||
do_check_eq(null, CSPSource.fromString("a#2-c.com", undefined, "http://a.com"));
|
||||
|
||||
//print(" --- Stop ignoring errors that print ---\n");
|
||||
|
||||
//"failed to parse host with port.");
|
||||
do_check_neq(null, CSPSource.create("a.com:23", "http://a.com"));
|
||||
do_check_neq(null, CSPSource.create("a.com:23", undefined, "http://a.com"));
|
||||
//"failed to parse host with scheme.");
|
||||
do_check_neq(null, CSPSource.create("https://a.com", "http://a.com"));
|
||||
do_check_neq(null, CSPSource.create("https://a.com", undefined, "http://a.com"));
|
||||
//"failed to parse host with scheme and port.");
|
||||
do_check_neq(null, CSPSource.create("https://a.com:200", "http://a.com"));
|
||||
do_check_neq(null, CSPSource.create("https://a.com:200", undefined, "http://a.com"));
|
||||
|
||||
//Check to make sure we don't match multiple instances with regex
|
||||
do_check_eq(null, CSPSource.create("http://foo.com:bar.com:23"));
|
||||
@ -193,7 +193,7 @@ test(
|
||||
test(
|
||||
function test_CSPSource_fromString_withSelf() {
|
||||
var src;
|
||||
src = CSPSource.create("a.com", "https://foobar.com:443");
|
||||
src = CSPSource.create("a.com", undefined, "https://foobar.com:443");
|
||||
//"src should inherit port *
|
||||
do_check_true(src.permits("https://a.com:443"));
|
||||
//"src should inherit and require https scheme
|
||||
@ -201,7 +201,7 @@ test(
|
||||
//"src should inherit scheme 'https'"
|
||||
do_check_true(src.permits("https://a.com"));
|
||||
|
||||
src = CSPSource.create("http://a.com", "https://foobar.com:443");
|
||||
src = CSPSource.create("http://a.com", undefined, "https://foobar.com:443");
|
||||
//"src should inherit and require http scheme"
|
||||
do_check_false(src.permits("https://a.com"));
|
||||
//"src should inherit scheme 'http'"
|
||||
@ -210,7 +210,7 @@ test(
|
||||
//"src should inherit default port for 'http'"
|
||||
do_check_true(src.permits("http://a.com:80"));
|
||||
|
||||
src = CSPSource.create("'self'", "https://foobar.com:443");
|
||||
src = CSPSource.create("'self'", undefined, "https://foobar.com:443");
|
||||
//"src should inherit port *
|
||||
do_check_true(src.permits("https://foobar.com:443"));
|
||||
//"src should inherit and require https scheme
|
||||
@ -220,7 +220,7 @@ test(
|
||||
//"src should reject other hosts"
|
||||
do_check_false(src.permits("https://a.com"));
|
||||
|
||||
src = CSPSource.create("javascript:", "https://foobar.com:443");
|
||||
src = CSPSource.create("javascript:", undefined, "https://foobar.com:443");
|
||||
//"hostless schemes should be parseable."
|
||||
var aUri = NetUtil.newURI("javascript:alert('foo');");
|
||||
do_check_true(src.permits(aUri));
|
||||
@ -260,7 +260,7 @@ test(
|
||||
function test_CSPSourceList_fromString_twohost() {
|
||||
var str = "foo.bar:21 https://ras.bar";
|
||||
var parsed = "http://foo.bar:21 https://ras.bar:443";
|
||||
var sd = CSPSourceList.fromString(str, URI("http://self.com:80"));
|
||||
var sd = CSPSourceList.fromString(str, undefined, URI("http://self.com:80"));
|
||||
//"two-host list should parse"
|
||||
do_check_neq(null,sd);
|
||||
//"two-host list should parse to two hosts"
|
||||
@ -272,8 +272,9 @@ test(
|
||||
test(
|
||||
function test_CSPSourceList_permits() {
|
||||
var nullSourceList = CSPSourceList.fromString("'none'");
|
||||
var simpleSourceList = CSPSourceList.fromString("a.com", URI("http://self.com"));
|
||||
var simpleSourceList = CSPSourceList.fromString("a.com", undefined, URI("http://self.com"));
|
||||
var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
|
||||
undefined,
|
||||
URI("http://self.com:88"));
|
||||
var allSourceList = CSPSourceList.fromString("*");
|
||||
var allAndMoreSourceList = CSPSourceList.fromString("* https://bar.com 'none'");
|
||||
@ -680,7 +681,7 @@ test(
|
||||
*/
|
||||
|
||||
var src;
|
||||
src = CSPSource.create("a.com", "https://foobar.com:4443");
|
||||
src = CSPSource.create("a.com", undefined, "https://foobar.com:4443");
|
||||
//"src should inherit and require https scheme
|
||||
do_check_false(src.permits("http://a.com"));
|
||||
//"src should inherit scheme 'https'"
|
||||
@ -688,7 +689,7 @@ test(
|
||||
//"src should get default port
|
||||
do_check_true(src.permits("https://a.com:443"));
|
||||
|
||||
src = CSPSource.create("http://a.com", "https://foobar.com:4443");
|
||||
src = CSPSource.create("http://a.com", undefined, "https://foobar.com:4443");
|
||||
//"src should require http scheme"
|
||||
do_check_false(src.permits("https://a.com"));
|
||||
//"src should keep scheme 'http'"
|
||||
@ -696,7 +697,7 @@ test(
|
||||
//"src should inherit default port for 'http'"
|
||||
do_check_true(src.permits("http://a.com:80"));
|
||||
|
||||
src = CSPSource.create("'self'", "https://foobar.com:4443");
|
||||
src = CSPSource.create("'self'", undefined, "https://foobar.com:4443");
|
||||
//"src should inherit nonstandard port from self
|
||||
do_check_true(src.permits("https://foobar.com:4443"));
|
||||
do_check_false(src.permits("https://foobar.com"));
|
||||
@ -716,9 +717,9 @@ test(
|
||||
* doesn't happen.
|
||||
*/
|
||||
|
||||
var p_none = CSPSourceList.fromString("'none'", "http://foo.com", false);
|
||||
var p_all = CSPSourceList.fromString("*", "http://foo.com", false);
|
||||
var p_one = CSPSourceList.fromString("bar.com", "http://foo.com", false);
|
||||
var p_none = CSPSourceList.fromString("'none'", undefined, "http://foo.com", false);
|
||||
var p_all = CSPSourceList.fromString("*", undefined, "http://foo.com", false);
|
||||
var p_one = CSPSourceList.fromString("bar.com", undefined, "http://foo.com", false);
|
||||
|
||||
do_check_false(p_none.equals(p_all));
|
||||
do_check_false(p_none.equals(p_one));
|
||||
|
Loading…
Reference in New Issue
Block a user