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.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | 'use strict'; |
michael@0 | 6 | |
michael@0 | 7 | module.metadata = { |
michael@0 | 8 | "stability": "unstable" |
michael@0 | 9 | }; |
michael@0 | 10 | |
michael@0 | 11 | let unescape = decodeURIComponent; |
michael@0 | 12 | exports.unescape = unescape; |
michael@0 | 13 | |
michael@0 | 14 | // encodes a string safely for application/x-www-form-urlencoded |
michael@0 | 15 | // adheres to RFC 3986 |
michael@0 | 16 | // see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURIComponent |
michael@0 | 17 | function escape(query) { |
michael@0 | 18 | return encodeURIComponent(query). |
michael@0 | 19 | replace(/%20/g, '+'). |
michael@0 | 20 | replace(/!/g, '%21'). |
michael@0 | 21 | replace(/'/g, '%27'). |
michael@0 | 22 | replace(/\(/g, '%28'). |
michael@0 | 23 | replace(/\)/g, '%29'). |
michael@0 | 24 | replace(/\*/g, '%2A'); |
michael@0 | 25 | } |
michael@0 | 26 | exports.escape = escape; |
michael@0 | 27 | |
michael@0 | 28 | // Converts an object of unordered key-vals to a string that can be passed |
michael@0 | 29 | // as part of a request |
michael@0 | 30 | function stringify(options, separator, assigner) { |
michael@0 | 31 | separator = separator || '&'; |
michael@0 | 32 | assigner = assigner || '='; |
michael@0 | 33 | // Explicitly return null if we have null, and empty string, or empty object. |
michael@0 | 34 | if (!options) |
michael@0 | 35 | return ''; |
michael@0 | 36 | |
michael@0 | 37 | // If content is already a string, just return it as is. |
michael@0 | 38 | if (typeof(options) == 'string') |
michael@0 | 39 | return options; |
michael@0 | 40 | |
michael@0 | 41 | // At this point we have a k:v object. Iterate over it and encode each value. |
michael@0 | 42 | // Arrays and nested objects will get encoded as needed. For example... |
michael@0 | 43 | // |
michael@0 | 44 | // { foo: [1, 2, { omg: 'bbq', 'all your base!': 'are belong to us' }], bar: 'baz' } |
michael@0 | 45 | // |
michael@0 | 46 | // will be encoded as |
michael@0 | 47 | // |
michael@0 | 48 | // foo[0]=1&foo[1]=2&foo[2][omg]=bbq&foo[2][all+your+base!]=are+belong+to+us&bar=baz |
michael@0 | 49 | // |
michael@0 | 50 | // Keys (including '[' and ']') and values will be encoded with |
michael@0 | 51 | // `escape` before returning. |
michael@0 | 52 | // |
michael@0 | 53 | // Execution was inspired by jQuery, but some details have changed and numeric |
michael@0 | 54 | // array keys are included (whereas they are not in jQuery). |
michael@0 | 55 | |
michael@0 | 56 | let encodedContent = []; |
michael@0 | 57 | function add(key, val) { |
michael@0 | 58 | encodedContent.push(escape(key) + assigner + escape(val)); |
michael@0 | 59 | } |
michael@0 | 60 | |
michael@0 | 61 | function make(key, value) { |
michael@0 | 62 | if (value && typeof(value) === 'object') |
michael@0 | 63 | Object.keys(value).forEach(function(name) { |
michael@0 | 64 | make(key + '[' + name + ']', value[name]); |
michael@0 | 65 | }); |
michael@0 | 66 | else |
michael@0 | 67 | add(key, value); |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | Object.keys(options).forEach(function(name) { make(name, options[name]); }); |
michael@0 | 71 | return encodedContent.join(separator); |
michael@0 | 72 | |
michael@0 | 73 | //XXXzpao In theory, we can just use a FormData object on 1.9.3, but I had |
michael@0 | 74 | // trouble getting that working. It would also be nice to stay |
michael@0 | 75 | // backwards-compat as long as possible. Keeping this in for now... |
michael@0 | 76 | // let formData = Cc['@mozilla.org/files/formdata;1']. |
michael@0 | 77 | // createInstance(Ci.nsIDOMFormData); |
michael@0 | 78 | // for ([k, v] in Iterator(content)) { |
michael@0 | 79 | // formData.append(k, v); |
michael@0 | 80 | // } |
michael@0 | 81 | // return formData; |
michael@0 | 82 | } |
michael@0 | 83 | exports.stringify = stringify; |
michael@0 | 84 | |
michael@0 | 85 | // Exporting aliases that nodejs implements just for the sake of |
michael@0 | 86 | // interoperability. |
michael@0 | 87 | exports.encode = stringify; |
michael@0 | 88 | exports.serialize = stringify; |
michael@0 | 89 | |
michael@0 | 90 | // Note: That `stringify` and `parse` aren't bijective as we use `stringify` |
michael@0 | 91 | // as it was implement in request module, but implement `parse` to match nodejs |
michael@0 | 92 | // behavior. |
michael@0 | 93 | // TODO: Make `stringify` implement API as in nodejs and figure out backwards |
michael@0 | 94 | // compatibility. |
michael@0 | 95 | function parse(query, separator, assigner) { |
michael@0 | 96 | separator = separator || '&'; |
michael@0 | 97 | assigner = assigner || '='; |
michael@0 | 98 | let result = {}; |
michael@0 | 99 | |
michael@0 | 100 | if (typeof query !== 'string' || query.length === 0) |
michael@0 | 101 | return result; |
michael@0 | 102 | |
michael@0 | 103 | query.split(separator).forEach(function(chunk) { |
michael@0 | 104 | let pair = chunk.split(assigner); |
michael@0 | 105 | let key = unescape(pair[0]); |
michael@0 | 106 | let value = unescape(pair.slice(1).join(assigner)); |
michael@0 | 107 | |
michael@0 | 108 | if (!(key in result)) |
michael@0 | 109 | result[key] = value; |
michael@0 | 110 | else if (Array.isArray(result[key])) |
michael@0 | 111 | result[key].push(value); |
michael@0 | 112 | else |
michael@0 | 113 | result[key] = [result[key], value]; |
michael@0 | 114 | }); |
michael@0 | 115 | |
michael@0 | 116 | return result; |
michael@0 | 117 | }; |
michael@0 | 118 | exports.parse = parse; |
michael@0 | 119 | // Exporting aliases that nodejs implements just for the sake of |
michael@0 | 120 | // interoperability. |
michael@0 | 121 | exports.decode = parse; |