bug 570505 - fix csp to avoid creating strings from URIs and un-hose test_bug558431. r=dveditz
authorTanvi Vyas <tvyas@mozilla.com>
Tue, 17 Apr 2012 06:16:05 -0700
changeset 95166 67818a1a19c39a6b041d4e3b9150e38b491bf1c1
parent 95165 372d32e0ea61376eb4c20443a2e3794345617195
child 95167 279264d06d08ba858f52a8e53cedfffd5c8db4eb
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdveditz
bugs570505, 558431
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 570505 - fix csp to avoid creating strings from URIs and un-hose test_bug558431. r=dveditz
content/base/src/CSPUtils.jsm
content/base/src/contentSecurityPolicy.js
content/base/test/unit/test_bug558431.js
content/base/test/unit/test_csputils.js
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -82,30 +82,30 @@ var gPrefObserver = {
 };
 
 
 function CSPWarning(aMsg, aSource, aScriptSample, aLineNum) {
   var textMessage = 'CSP WARN:  ' + aMsg + "\n";
 
   var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
                     .createInstance(Components.interfaces.nsIScriptError);
-  consoleMsg.init('CSP: ' + aMsg, aSource, aScriptSample, aLineNum, 0,
+  consoleMsg.init(textMessage, aSource, aScriptSample, aLineNum, 0,
                   Components.interfaces.nsIScriptError.warningFlag,
                   "Content Security Policy");
   Components.classes["@mozilla.org/consoleservice;1"]
                     .getService(Components.interfaces.nsIConsoleService)
                     .logMessage(consoleMsg);
 }
 
 function CSPError(aMsg) {
   var textMessage = 'CSP ERROR:  ' + aMsg + "\n";
 
   var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
                     .createInstance(Components.interfaces.nsIScriptError);
-  consoleMsg.init('CSP: ' + aMsg, null, null, 0, 0,
+  consoleMsg.init(textMessage, null, null, 0, 0,
                   Components.interfaces.nsIScriptError.errorFlag,
                   "Content Security Policy");
   Components.classes["@mozilla.org/consoleservice;1"]
                     .getService(Components.interfaces.nsIConsoleService)
                     .logMessage(consoleMsg);
 }
 
 function CSPdebug(aMsg) {
@@ -208,17 +208,17 @@ CSPRep.OPTIONS_DIRECTIVE = "options";
 CSPRep.ALLOW_DIRECTIVE   = "allow";
 
 /**
   * Factory to create a new CSPRep, parsed from a string.
   *
   * @param aStr
   *        string rep of a CSP
   * @param self (optional)
-  *        string or CSPSource representing the "self" source
+  *        URI representing the "self" source
   * @param docRequest (optional)
   *        request for the parent document which may need to be suspended
   *        while the policy-uri is asynchronously fetched
   * @param csp (optional)
   *        the CSP object to update once the policy has been fetched
   * @returns
   *        an instance of CSPRep
   */
@@ -226,18 +226,16 @@ CSPRep.fromString = function(aStr, self,
   var SD = CSPRep.SRC_DIRECTIVES;
   var UD = CSPRep.URI_DIRECTIVES;
   var aCSPR = new CSPRep();
   aCSPR._originalText = aStr;
 
   var selfUri = null;
   if (self instanceof Components.interfaces.nsIURI)
     selfUri = self.clone();
-  else if (self)
-    selfUri = gIoService.newURI(self, null, null);
 
   var dirs = aStr.split(";");
 
   directive:
   for each(var dir in dirs) {
     dir = dir.trim();
     if (dir.length < 1) continue;
 
@@ -447,18 +445,18 @@ CSPRep.prototype = {
   /**
    * Generates canonical string representation of the policy.
    */
   toString:
   function csp_toString() {
     var dirs = [];
 
     if (this._allowEval || this._allowInlineScripts) {
-      dirs.push("options " + (this._allowEval ? "eval-script" : "")
-                           + (this._allowInlineScripts ? "inline-script" : ""));
+      dirs.push("options" + (this._allowEval ? " eval-script" : "")
+                           + (this._allowInlineScripts ? " inline-script" : ""));
     }
     for (var i in this._directives) {
       if (this._directives[i]) {
         dirs.push(i + " " + this._directives[i].toString());
       }
     }
     return dirs.join("; ");
   },
@@ -599,30 +597,36 @@ function CSPSourceList() {
 }
 
 /**
  * Factory to create a new CSPSourceList, parsed from a string.
  *
  * @param aStr
  *        string rep of a CSP Source List
  * @param self (optional)
- *        string or CSPSource representing the "self" source
+ *        URI or CSPSource representing the "self" source
  * @param enforceSelfChecks (optional)
  *        if present, and "true", will check to be sure "self" has the
  *        appropriate values to inherit when they are omitted from the source.
  * @returns
  *        an instance of CSPSourceList 
  */
 CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
   // Source list is:
   //    <host-dir-value> ::= <source-list>
   //                       | "'none'"
   //    <source-list>    ::= <source>
   //                       | <source-list>" "<source>
 
+  /* If self parameter is passed, convert to CSPSource,
+     unless it is already a CSPSource. */
+  if(self && !(self instanceof CSPSource)) {
+     self = CSPSource.create(self);
+  }
+
   var slObj = new CSPSourceList();
   if (aStr === "'none'")
     return slObj;
 
   if (aStr === "*") {
     slObj._permitAllSources = true;
     return slObj;
   }
@@ -805,16 +809,25 @@ function CSPSource() {
 }
 
 /**
  * General factory method to create a new source from one of the following
  * types:
  *  - nsURI
  *  - string
  *  - CSPSource (clone)
+ * @param aData 
+ *        string, nsURI, or CSPSource
+ * @param self (optional)
+ *	  if present, string, URI, or CSPSource representing the "self" resource 
+ * @param enforceSelfChecks (optional)
+ *	  if present, and "true", will check to be sure "self" has the
+ *        appropriate values to inherit when they are omitted from the source.
+ * @returns
+ *        an instance of CSPSource
  */
 CSPSource.create = function(aData, self, enforceSelfChecks) {
   if (typeof aData === 'string')
     return CSPSource.fromString(aData, self, enforceSelfChecks);
 
   if (aData instanceof Components.interfaces.nsIURI)
     return CSPSource.fromURI(aData, self, enforceSelfChecks);
 
@@ -907,17 +920,17 @@ CSPSource.fromURI = function(aURI, self,
 };
 
 /**
  * Factory to create a new CSPSource, parsed from a string.
  *
  * @param aStr
  *        string rep of a CSP Source
  * @param self (optional)
- *        string or CSPSource representing the "self" source
+ *        string, URI, or CSPSource representing the "self" source
  * @param enforceSelfChecks (optional)
  *        if present, and "true", will check to be sure "self" has the
  *        appropriate values to inherit when they are omitted from aURI.
  * @returns
  *        an instance of CSPSource 
  */
 CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
   if (!aStr)
--- a/content/base/src/contentSecurityPolicy.js
+++ b/content/base/src/contentSecurityPolicy.js
@@ -234,18 +234,20 @@ ContentSecurityPolicy.prototype = {
       selfURI = selfURI.innermostURI;
     }
 
     // stay uninitialized until policy merging is done
     this._isInitialized = false;
 
     // If there is a policy-uri, fetch the policy, then re-call this function.
     // (1) parse and create a CSPRep object
+    // Note that we pass the full URI since when it's parsed as 'self' to construct a 
+    // CSPSource only the scheme, host, and port are kept. 
     var newpolicy = CSPRep.fromString(aPolicy,
-                                      selfURI.scheme + "://" + selfURI.hostPort,
+				      selfURI,
                                       this._docRequest,
                                       this);
 
     // (2) Intersect the currently installed CSPRep object with the new one
     var intersect = this._policy.intersectWith(newpolicy);
  
     // (3) Save the result
     this._policy = intersect;
--- a/content/base/test/unit/test_bug558431.js
+++ b/content/base/test/unit/test_bug558431.js
@@ -5,38 +5,46 @@ var httpserv = null;
 
 const POLICY_FROM_URI = "allow 'self'; img-src *";
 const POLICY_PORT = 9000;
 const POLICY_URI = "http://localhost:" + POLICY_PORT + "/policy";
 const POLICY_URI_RELATIVE = "/policy";
 const DOCUMENT_URI = "http://localhost:" + POLICY_PORT + "/document";
 const CSP_DOC_BODY = "CSP doc content";
 const SD = CSPRep.SRC_DIRECTIVES;
-const MAX_TESTS = 2;
-var TESTS_COMPLETED = 0;
+
+// this will get populated by run_tests()
+var TESTS = [];
 
-var cspr, cspr_static;
+// helper to make URIs
+function mkuri(foo) {
+  return Components.classes["@mozilla.org/network/io-service;1"]
+                           .getService(Components.interfaces.nsIIOService)
+                           .newURI(foo, null, null);
+}
 
 // helper to use .equals on stuff
 function do_check_equivalent(foo, bar, stack) {
-  if (!stack) 
+  if (!stack)
     stack = Components.stack.caller;
 
   var text = foo + ".equals(" + bar + ")";
 
   if (foo.equals && foo.equals(bar)) {
     dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
          stack.lineNumber + "] " + text + "\n");
     return;
   }
   do_throw(text, stack);
 }
 
-function listener() {
+function listener(csp, cspr_static) {
   this.buffer = "";
+  this._csp = csp;
+  this._cspr_static = cspr_static;
 }
 
 listener.prototype = {
   onStartRequest: function (request, ctx) {
   },
 
   onDataAvailable: function (request, ctx, stream, offset, count) {
     var sInputStream = Cc["@mozilla.org/scriptableinputstream;1"]
@@ -44,46 +52,55 @@ listener.prototype = {
     sInputStream.init(stream);
     this.buffer = this.buffer.concat(sInputStream.read(count));
   },
 
   onStopRequest: function (request, ctx, status) {
     // make sure that we have the full document content, guaranteeing that
     // the document channel has been resumed, before we do the comparisons
     if (this.buffer == CSP_DOC_BODY) {
-      // "policy-uri failed to load"
-      do_check_neq(null, cspr);
+
+      // need to re-grab cspr since it may have changed inside the document's
+      // nsIContentSecurityPolicy instance.  The problem is, this cspr_str is a
+      // string and not a policy due to the way it's exposed from
+      // nsIContentSecurityPolicy, so we have to re-parse it.
+      let cspr_str = this._csp.policy;
+      let cspr = CSPRep.fromString(cspr_str, mkuri(DOCUMENT_URI));
 
-      // other directives inherit self
-      for (var i in SD) {
-        do_check_equivalent(cspr._directives[SD[i]],
-                            cspr_static._directives[SD[i]]);
-      }
+      // and in reparsing it, we lose the 'self' relationships, so need to also
+      // reparse the static one (or find a way to resolve 'self' in the parsed
+      // policy when doing comparisons).
+      let cspr_static_str = this._cspr_static.toString();
+      let cspr_static_reparse = CSPRep.fromString(cspr_static_str, mkuri(DOCUMENT_URI));
 
-      do_test_finished();
-      TESTS_COMPLETED++;
+      // not null, and one policy .equals the other one
+      do_check_neq(null, cspr);
+      do_check_true(cspr.equals(cspr_static_reparse));
+
       // final teardown
-      if (TESTS_COMPLETED == MAX_TESTS) {
-        httpserv.stop(function(){});
+      if (TESTS.length == 0) {
+        httpserv.stop(do_test_finished);
+      } else {
+        do_test_finished();
+        (TESTS.shift())();
       }
     }
   }
 };
 
 function run_test() {
   httpserv = new nsHttpServer();
   httpserv.registerPathHandler("/document", csp_doc_response);
   httpserv.registerPathHandler("/policy", csp_policy_response);
   httpserv.start(POLICY_PORT);
+  TESTS = [ test_CSPRep_fromPolicyURI, test_CSPRep_fromRelativePolicyURI ];
 
-  var tests = [ test_CSPRep_fromPolicyURI, test_CSPRep_fromRelativePolicyURI];
-  for (var i = 0 ; i < tests.length ; i++) {
-    tests[i]();
-    do_test_pending();
-  }
+  // when this triggers the "onStopRequest" callback, it'll
+  // go to the next test.
+  (TESTS.shift())();
 }
 
 function makeChan(url) {
   var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
   var chan = ios.newChannel(url, null, null).QueryInterface(Ci.nsIHttpChannel);
   return chan;
 }
 
@@ -96,32 +113,46 @@ function csp_doc_response(metadata, resp
 function csp_policy_response(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 200, "OK");
   response.setHeader("Content-Type", "text/csp", false);
   response.bodyOutputStream.write(POLICY_FROM_URI, POLICY_FROM_URI.length);
 }
 
 ///////////////////// TEST POLICY_URI //////////////////////
 function test_CSPRep_fromPolicyURI() {
-  var csp = Components.classes["@mozilla.org/contentsecuritypolicy;1"]
-    .createInstance[Components.interfaces.nsIContentSecurityPolicy];
+  do_test_pending();
+  let csp = Cc["@mozilla.org/contentsecuritypolicy;1"]
+              .createInstance(Ci.nsIContentSecurityPolicy);
   // once the policy-uri is returned we will compare our static CSPRep with one
   // we generated from the content we got back from the network to make sure
   // they are equivalent
-  cspr_static = CSPRep.fromString(POLICY_FROM_URI, DOCUMENT_URI);
+  let cspr_static = CSPRep.fromString(POLICY_FROM_URI, mkuri(DOCUMENT_URI));
+
   // simulates the request for the parent document
   var docChan = makeChan(DOCUMENT_URI);
-  docChan.asyncOpen(new listener(), null);
-  cspr = CSPRep.fromString("policy-uri " + POLICY_URI, DOCUMENT_URI, docChan, csp);
+  docChan.asyncOpen(new listener(csp, cspr_static), null);
+
+  // the resulting policy here can be discarded, since it's going to be
+  // "allow *"; when the policy-uri fetching call-back happens, the *real*
+  // policy will be in csp.policy
+  CSPRep.fromString("policy-uri " + POLICY_URI,
+                    mkuri(DOCUMENT_URI), docChan, csp);
 }
 
 function test_CSPRep_fromRelativePolicyURI() {
-  var csp = Components.classes["@mozilla.org/contentsecuritypolicy;1"]
-    .createInstance[Components.interfaces.nsIContentSecurityPolicy];
+  do_test_pending();
+  let csp = Cc["@mozilla.org/contentsecuritypolicy;1"]
+              .createInstance(Ci.nsIContentSecurityPolicy);
   // once the policy-uri is returned we will compare our static CSPRep with one
   // we generated from the content we got back from the network to make sure
   // they are equivalent
-  cspr_static = CSPRep.fromString(POLICY_FROM_URI, DOCUMENT_URI);
+  let cspr_static = CSPRep.fromString(POLICY_FROM_URI, mkuri(DOCUMENT_URI));
+
   // simulates the request for the parent document
   var docChan = makeChan(DOCUMENT_URI);
-  docChan.asyncOpen(new listener(), null);
-  cspr = CSPRep.fromString("policy-uri " + POLICY_URI_RELATIVE, DOCUMENT_URI, docChan, csp);
+  docChan.asyncOpen(new listener(csp, cspr_static), null);
+
+  // the resulting policy here can be discarded, since it's going to be
+  // "allow *"; when the policy-uri fetching call-back happens, the *real*
+  // policy will be in csp.policy
+  CSPRep.fromString("policy-uri " + POLICY_URI_RELATIVE,
+                    mkuri(DOCUMENT_URI), docChan, csp);
 }
--- a/content/base/test/unit/test_csputils.js
+++ b/content/base/test/unit/test_csputils.js
@@ -42,16 +42,24 @@ do_load_httpd_js();
 
 var httpServer = new nsHttpServer();
 
 const POLICY_FROM_URI = "allow 'self'; img-src *";
 const POLICY_PORT = 9000;
 const POLICY_URI = "http://localhost:" + POLICY_PORT + "/policy";
 const POLICY_URI_RELATIVE = "/policy";
 
+//converts string to nsIURI
+function URI(uriString) {
+  var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+                .getService(Components.interfaces.nsIIOService);
+  return ioService.newURI(uriString, null, null);
+}
+
+
 // helper to assert that an array has the given value somewhere.
 function do_check_in_array(arr, val, stack) {
   if (!stack)
     stack = Components.stack.caller;
 
   var text = val + " in [" + arr.join(",") + "]";
 
   for(var i in arr) {
@@ -267,31 +275,31 @@ test(
       do_check_true(CSPSourceList.fromString("https://f-oo.bar:3f").isNone());
       //print(" --- Stop ignoring errors that print ---\n");
     });
 
 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, "http://self.com:80");
+      var sd = CSPSourceList.fromString(str, URI("http://self.com:80"));
       //"two-host list should parse"
       do_check_neq(null,sd);
       //"two-host list should parse to two hosts"
       do_check_eq(2, sd._sources.length);
       //"two-host list should contain original data"
       do_check_eq(parsed, sd.toString());
     });
 
 test(
     function test_CSPSourceList_permits() {
       var nullSourceList = CSPSourceList.fromString("'none'");
-      var simpleSourceList = CSPSourceList.fromString("a.com", "http://self.com");
+      var simpleSourceList = CSPSourceList.fromString("a.com", URI("http://self.com"));
       var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
-                                                      "http://self.com:88");
+                                                      URI("http://self.com:88"));
       var allSourceList = CSPSourceList.fromString("*");
 
       //'none' should permit none."
       do_check_false( nullSourceList.permits("http://a.com"));
       //a.com should permit a.com"
       do_check_true( simpleSourceList.permits("http://a.com"));
       //wrong host"
       do_check_false( simpleSourceList.permits("http://b.com"));
@@ -357,17 +365,17 @@ test(
       // check default init
       //ASSERT(!(new CSPRep())._isInitialized, "Uninitialized rep thinks it is.")
 
       var cspr;
       var cspr_allowval;
       var SD = CSPRep.SRC_DIRECTIVES;
 
       // check default policy "allow *"
-      cspr = CSPRep.fromString("allow *", "http://self.com:80");
+      cspr = CSPRep.fromString("allow *", URI("http://self.com:80"));
       // "DEFAULT_SRC directive is missing when specified in fromString"
       do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
 
       // ... and check that the other directives were auto-filled with the
       // DEFAULT_SRC one.
       cspr_allowval = cspr._directives[SD.DEFAULT_SRC];
       for(var d in SD) {
         //"Missing key " + d
@@ -379,33 +387,33 @@ test(
 
 
 test(
     function test_CSPRep_defaultSrc() {
       var cspr, cspr_default_val, cspr_allow;
       var SD = CSPRep.SRC_DIRECTIVES;
 
       // apply policy of "default-src *" (e.g. "allow *")
-      cspr = CSPRep.fromString("default-src *", "http://self.com:80");
+      cspr = CSPRep.fromString("default-src *", URI("http://self.com:80"));
       // "DEFAULT_SRC directive is missing when specified in fromString"
       do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
 
       // check that the other directives were auto-filled with the
       // DEFAULT_SRC one.
       cspr_default_val = cspr._directives[SD.DEFAULT_SRC];
       for (var d in SD) {
         do_check_has_key(cspr._directives, SD[d]);
         // "Implicit directive " + d + " has non-default-src value."
         do_check_eq(cspr._directives[SD[d]].toString(), cspr_default_val.toString());
       }
 
       // check that |allow *| and |default-src *| are parsed equivalently and
       // result in the same set of explicit policy directives
-      cspr = CSPRep.fromString("default-src *", "http://self.com:80");
-      cspr_allow = CSPRep.fromString("allow *", "http://self.com:80");
+      cspr = CSPRep.fromString("default-src *", URI("http://self.com:80"));
+      cspr_allow = CSPRep.fromString("allow *", URI("http://self.com:80"));
 
       for (var d in SD) {
         do_check_equivalent(cspr._directives[SD[d]],
                             cspr_allow._directives[SD[d]]);
       }
     });
 
 
@@ -413,17 +421,17 @@ test(
     function test_CSPRep_fromString_oneDir() {
 
       var cspr;
       var SD = CSPRep.SRC_DIRECTIVES;
       var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.FRAME_SRC];
 
       // check one-directive policies
       cspr = CSPRep.fromString("allow bar.com; script-src https://foo.com", 
-                               "http://self.com");
+                               URI("http://self.com"));
 
       for(var x in DEFAULTS) {
         //DEFAULTS[x] + " does not use default rule."
         do_check_false(cspr.permits("http://bar.com:22", DEFAULTS[x]));
         //DEFAULTS[x] + " does not use default rule."
         do_check_true(cspr.permits("http://bar.com:80", DEFAULTS[x]));
         //DEFAULTS[x] + " does not use default rule."
         do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
@@ -441,17 +449,17 @@ test(
       var cspr;
       var SD = CSPRep.SRC_DIRECTIVES;
       var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC];
 
       // check two-directive policies
       var polstr = "allow allow.com; "
                   + "script-src https://foo.com; "
                   + "img-src bar.com:*";
-      cspr = CSPRep.fromString(polstr, "http://self.com");
+      cspr = CSPRep.fromString(polstr, URI("http://self.com"));
 
       for(var x in DEFAULTS) {
         do_check_true(cspr.permits("http://allow.com", DEFAULTS[x]));
         //DEFAULTS[x] + " does not use default rule.
         do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
         //DEFAULTS[x] + " does not use default rule.
         do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x]));
         //DEFAULTS[x] + " does not use default rule.
@@ -473,17 +481,17 @@ test(
 
 test(function test_CSPRep_fromString_withself() {
       var cspr;
       var SD = CSPRep.SRC_DIRECTIVES;
       var self = "https://self.com:34";
 
       // check one-directive policies
       cspr = CSPRep.fromString("allow 'self'; script-src 'self' https://*:*",
-                              self);
+                              URI(self));
       //"img-src does not enforce default rule, 'self'.
       do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
       //"img-src does not allow self
       do_check_true(cspr.permits(self, SD.IMG_SRC));
       //"script-src is too relaxed
       do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC));
       //"script-src should allow self
       do_check_true(cspr.permits(self, SD.SCRIPT_SRC));
@@ -493,26 +501,26 @@ test(function test_CSPRep_fromString_wit
 
 //////////////// TEST FRAME ANCESTOR DEFAULTS /////////////////
 // (see bug 555068)
 test(function test_FrameAncestor_defaults() {
       var cspr;
       var SD = CSPRep.SRC_DIRECTIVES;
       var self = "http://self.com:34";
 
-      cspr = CSPRep.fromString("allow 'none'", self);
+      cspr = CSPRep.fromString("allow 'none'", URI(self));
 
       //"frame-ancestors should default to * not 'allow' value"
       do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS));
       do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS));
       do_check_true(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS));
       do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS));
       do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS));
 
-      cspr = CSPRep.fromString("allow 'none'; frame-ancestors 'self'", self);
+      cspr = CSPRep.fromString("allow 'none'; frame-ancestors 'self'", URI(self));
 
       //"frame-ancestors should only allow self"
       do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS));
       do_check_false(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS));
       do_check_false(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS));
       do_check_false(cspr.permits("http://self.com", SD.FRAME_ANCESTORS));
       do_check_false(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS));
      });
@@ -526,55 +534,55 @@ test(function test_CSP_ReportURI_parsing
       var uri_valid_absolute = self + "/report.py";
       var uri_invalid_host_absolute = "http://foo.org:34/report.py";
       var uri_valid_relative = "/report.py";
       var uri_valid_relative_expanded = self + uri_valid_relative;
       var uri_valid_relative2 = "foo/bar/report.py";
       var uri_valid_relative2_expanded = self + "/" + uri_valid_relative2;
       var uri_invalid_relative = "javascript:alert(1)";
 
-      cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_absolute, self);
+      cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_absolute, URI(self));
       parsedURIs = cspr.getReportURIs().split(/\s+/);
       do_check_in_array(parsedURIs, uri_valid_absolute);
       do_check_eq(parsedURIs.length, 1);
 
-      cspr = CSPRep.fromString("allow *; report-uri " + uri_invalid_host_absolute, self);
+      cspr = CSPRep.fromString("allow *; report-uri " + uri_invalid_host_absolute, URI(self));
       parsedURIs = cspr.getReportURIs().split(/\s+/);
       do_check_in_array(parsedURIs, "");
       do_check_eq(parsedURIs.length, 1); // the empty string is in there.
 
-      cspr = CSPRep.fromString("allow *; report-uri " + uri_invalid_relative, self);
+      cspr = CSPRep.fromString("allow *; report-uri " + uri_invalid_relative, URI(self));
       parsedURIs = cspr.getReportURIs().split(/\s+/);
       do_check_in_array(parsedURIs, "");
       do_check_eq(parsedURIs.length, 1);
 
-      cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_relative, self);
+      cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_relative, URI(self));
       parsedURIs = cspr.getReportURIs().split(/\s+/);
       do_check_in_array(parsedURIs, uri_valid_relative_expanded);
       do_check_eq(parsedURIs.length, 1);
 
-      cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_relative2, self);
+      cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_relative2, URI(self));
       parsedURIs = cspr.getReportURIs().split(/\s+/);
       dump(parsedURIs.length);
       do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
       do_check_eq(parsedURIs.length, 1);
 
       // combination!
       cspr = CSPRep.fromString("allow *; report-uri " +
                                uri_valid_relative2 + " " +
-                               uri_valid_absolute, self);
+                               uri_valid_absolute, URI(self));
       parsedURIs = cspr.getReportURIs().split(/\s+/);
       do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
       do_check_in_array(parsedURIs, uri_valid_absolute);
       do_check_eq(parsedURIs.length, 2);
 
       cspr = CSPRep.fromString("allow *; report-uri " +
                                uri_valid_relative2 + " " +
                                uri_invalid_host_absolute + " " +
-                               uri_valid_absolute, self);
+                               uri_valid_absolute, URI(self));
       parsedURIs = cspr.getReportURIs().split(/\s+/);
       do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
       do_check_in_array(parsedURIs, uri_valid_absolute);
       do_check_eq(parsedURIs.length, 2);
     });
 
 test(
     function test_bug672961_withNonstandardSelfPort() {
@@ -626,21 +634,21 @@ test(
 
 test(function test_CSPRep_fromPolicyURI_failswhenmixed() {
         var cspr;
         var self = "http://localhost:" + POLICY_PORT;
         var closed_policy = CSPRep.fromString("allow 'none'");
         var my_uri_policy = "policy-uri " + POLICY_URI;
 
         //print(" --- Ignore the following two errors if they print ---");
-        cspr = CSPRep.fromString("allow *; " + my_uri_policy, self);
+        cspr = CSPRep.fromString("allow *; " + my_uri_policy, URI(self));
 
         //"Parsing should fail when 'policy-uri' is mixed with allow directive"
         do_check_equivalent(cspr, closed_policy);
-        cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, self);
+        cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, URI(self));
 
         //"Parsing should fail when 'policy-uri' is mixed with other directives"
         do_check_equivalent(cspr, closed_policy);
         //print(" --- Stop ignoring errors that print ---\n");
 
     });
 */