addon-sdk/source/lib/sdk/url.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 "use strict";
     6 module.metadata = {
     7   "stability": "experimental"
     8 };
    10 const { Cc, Ci, Cr } = require("chrome");
    12 const { Class } = require("./core/heritage");
    13 const base64 = require("./base64");
    14 var tlds = Cc["@mozilla.org/network/effective-tld-service;1"]
    15           .getService(Ci.nsIEffectiveTLDService);
    17 var ios = Cc['@mozilla.org/network/io-service;1']
    18           .getService(Ci.nsIIOService);
    20 var resProt = ios.getProtocolHandler("resource")
    21               .QueryInterface(Ci.nsIResProtocolHandler);
    23 var URLParser = Cc["@mozilla.org/network/url-parser;1?auth=no"]
    24                 .getService(Ci.nsIURLParser);
    26 function newURI(uriStr, base) {
    27   try {
    28     let baseURI = base ? ios.newURI(base, null, null) : null;
    29     return ios.newURI(uriStr, null, baseURI);
    30   }
    31   catch (e) {
    32     if (e.result == Cr.NS_ERROR_MALFORMED_URI) {
    33       throw new Error("malformed URI: " + uriStr);
    34     }
    35     if (e.result == Cr.NS_ERROR_FAILURE ||
    36         e.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
    37       throw new Error("invalid URI: " + uriStr);
    38     }
    39   }
    40 }
    42 function resolveResourceURI(uri) {
    43   var resolved;
    44   try {
    45     resolved = resProt.resolveURI(uri);
    46   }
    47   catch (e) {
    48     if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
    49       throw new Error("resource does not exist: " + uri.spec);
    50     }
    51   }
    52   return resolved;
    53 }
    55 let fromFilename = exports.fromFilename = function fromFilename(path) {
    56   var file = Cc['@mozilla.org/file/local;1']
    57              .createInstance(Ci.nsILocalFile);
    58   file.initWithPath(path);
    59   return ios.newFileURI(file).spec;
    60 };
    62 let toFilename = exports.toFilename = function toFilename(url) {
    63   var uri = newURI(url);
    64   if (uri.scheme == "resource")
    65     uri = newURI(resolveResourceURI(uri));
    66   if (uri.scheme == "chrome") {
    67     var channel = ios.newChannelFromURI(uri);
    68     try {
    69       channel = channel.QueryInterface(Ci.nsIFileChannel);
    70       return channel.file.path;
    71     }
    72     catch (e) {
    73       if (e.result == Cr.NS_NOINTERFACE) {
    74         throw new Error("chrome url isn't on filesystem: " + url);
    75       }
    76     }
    77   }
    78   if (uri.scheme == "file") {
    79     var file = uri.QueryInterface(Ci.nsIFileURL).file;
    80     return file.path;
    81   }
    82   throw new Error("cannot map to filename: " + url);
    83 };
    85 function URL(url, base) {
    86   if (!(this instanceof URL)) {
    87      return new URL(url, base);
    88   }
    90   var uri = newURI(url, base);
    92   var userPass = null;
    93   try {
    94     userPass = uri.userPass ? uri.userPass : null;
    95   }
    96   catch (e) {
    97     if (e.result != Cr.NS_ERROR_FAILURE) {
    98       throw e;
    99     }
   100   }
   102   var host = null;
   103   try {
   104     host = uri.host;
   105   }
   106   catch (e) {
   107     if (e.result != Cr.NS_ERROR_FAILURE) {
   108       throw e;
   109     }
   110   }
   112   var port = null;
   113   try {
   114     port = uri.port == -1 ? null : uri.port;
   115   }
   116   catch (e) {
   117     if (e.result != Cr.NS_ERROR_FAILURE) {
   118       throw e;
   119     }
   120   }
   122   let uriData = [uri.path, uri.path.length, {}, {}, {}, {}, {}, {}];
   123   URLParser.parsePath.apply(URLParser, uriData);
   124   let [{ value: filepathPos }, { value: filepathLen },
   125     { value: queryPos }, { value: queryLen },
   126     { value: refPos }, { value: refLen }] = uriData.slice(2);
   128   let hash = uri.ref ? "#" + uri.ref : "";
   129   let pathname = uri.path.substr(filepathPos, filepathLen);
   130   let search = uri.path.substr(queryPos, queryLen);
   131   search = search ? "?" + search : "";
   133   this.__defineGetter__("scheme", function() uri.scheme);
   134   this.__defineGetter__("userPass", function() userPass);
   135   this.__defineGetter__("host", function() host);
   136   this.__defineGetter__("hostname", function() host);
   137   this.__defineGetter__("port", function() port);
   138   this.__defineGetter__("path", function() uri.path);
   139   this.__defineGetter__("pathname", function() pathname);
   140   this.__defineGetter__("hash", function() hash);
   141   this.__defineGetter__("href", function() uri.spec);
   142   this.__defineGetter__("origin", function() uri.prePath);
   143   this.__defineGetter__("protocol", function() uri.scheme + ":");
   144   this.__defineGetter__("search", function() search);
   146   Object.defineProperties(this, {
   147     toString: {
   148       value: function URL_toString() new String(uri.spec).toString(),
   149       enumerable: false
   150     },
   151     valueOf: {
   152       value: function() new String(uri.spec).valueOf(),
   153       enumerable: false
   154     },
   155     toSource: {
   156       value: function() new String(uri.spec).toSource(),
   157       enumerable: false
   158     }
   159   });
   161   return this;
   162 };
   164 URL.prototype = Object.create(String.prototype);
   165 exports.URL = URL;
   167 /**
   168  * Parse and serialize a Data URL.
   169  *
   170  * See: http://tools.ietf.org/html/rfc2397
   171  *
   172  * Note: Could be extended in the future to decode / encode automatically binary
   173  * data.
   174  */
   175 const DataURL = Class({
   177   get base64 () {
   178     return "base64" in this.parameters;
   179   },
   181   set base64 (value) {
   182     if (value)
   183       this.parameters["base64"] = "";
   184     else
   185       delete this.parameters["base64"];
   186   },
   187   /**
   188   * Initialize the Data URL object. If a uri is given, it will be parsed.
   189   *
   190   * @param {String} [uri] The uri to parse
   191   *
   192   * @throws {URIError} if the Data URL is malformed
   193    */
   194   initialize: function(uri) {
   195     // Due to bug 751834 it is not possible document and define these
   196     // properties in the prototype.
   198     /**
   199      * An hashmap that contains the parameters of the Data URL. By default is
   200      * empty, that accordingly to RFC is equivalent to {"charset" : "US-ASCII"}
   201      */
   202     this.parameters = {};
   204     /**
   205      * The MIME type of the data. By default is empty, that accordingly to RFC
   206      * is equivalent to "text/plain"
   207      */
   208     this.mimeType = "";
   210     /**
   211      * The string that represent the data in the Data URL
   212      */
   213     this.data = "";
   215     if (typeof uri === "undefined")
   216       return;
   218     uri = String(uri);
   220     let matches = uri.match(/^data:([^,]*),(.*)$/i);
   222     if (!matches)
   223       throw new URIError("Malformed Data URL: " + uri);
   225     let mediaType = matches[1].trim();
   227     this.data = decodeURIComponent(matches[2].trim());
   229     if (!mediaType)
   230       return;
   232     let parametersList = mediaType.split(";");
   234     this.mimeType = parametersList.shift().trim();
   236     for (let parameter, i = 0; parameter = parametersList[i++];) {
   237       let pairs = parameter.split("=");
   238       let name = pairs[0].trim();
   239       let value = pairs.length > 1 ? decodeURIComponent(pairs[1].trim()) : "";
   241       this.parameters[name] = value;
   242     }
   244     if (this.base64)
   245       this.data = base64.decode(this.data);
   247   },
   249   /**
   250    * Returns the object as a valid Data URL string
   251    *
   252    * @returns {String} The Data URL
   253    */
   254   toString : function() {
   255     let parametersList = [];
   257     for (let name in this.parameters) {
   258       let encodedParameter = encodeURIComponent(name);
   259       let value = this.parameters[name];
   261       if (value)
   262         encodedParameter += "=" + encodeURIComponent(value);
   264       parametersList.push(encodedParameter);
   265     }
   267     // If there is at least a parameter, add an empty string in order
   268     // to start with a `;` on join call.
   269     if (parametersList.length > 0)
   270       parametersList.unshift("");
   272     let data = this.base64 ? base64.encode(this.data) : this.data;
   274     return "data:" +
   275       this.mimeType +
   276       parametersList.join(";") + "," +
   277       encodeURIComponent(data);
   278   }
   279 });
   281 exports.DataURL = DataURL;
   283 let getTLD = exports.getTLD = function getTLD (url) {
   284   let uri = newURI(url.toString());
   285   let tld = null;
   286   try {
   287     tld = tlds.getPublicSuffix(uri);
   288   }
   289   catch (e) {
   290     if (e.result != Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS &&
   291         e.result != Cr.NS_ERROR_HOST_IS_IP_ADDRESS) {
   292       throw e;
   293     }
   294   }
   295   return tld;
   296 };
   298 let isValidURI = exports.isValidURI = function (uri) {
   299   try {
   300     newURI(uri);
   301   }
   302   catch(e) {
   303     return false;
   304   }
   305   return true;
   306 }
   308 function isLocalURL(url) {
   309   if (String.indexOf(url, './') === 0)
   310     return true;
   312   try {
   313     return ['resource', 'data', 'chrome'].indexOf(URL(url).scheme) > -1;
   314   }
   315   catch(e) {}
   317   return false;
   318 }
   319 exports.isLocalURL = isLocalURL;

mercurial