Sat, 03 Jan 2015 20:18:00 +0100
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;