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 | const { Cc, Ci, Cr, Cm, components: { classesByID } } = require('chrome'); |
michael@0 | 12 | const { registerFactory, unregisterFactory, isCIDRegistered } = |
michael@0 | 13 | Cm.QueryInterface(Ci.nsIComponentRegistrar); |
michael@0 | 14 | |
michael@0 | 15 | const { merge } = require('../util/object'); |
michael@0 | 16 | const { Class, extend, mix } = require('../core/heritage'); |
michael@0 | 17 | const { uuid } = require('../util/uuid'); |
michael@0 | 18 | |
michael@0 | 19 | // This is a base prototype, that provides bare bones of XPCOM. JS based |
michael@0 | 20 | // components can be easily implement by extending it. |
michael@0 | 21 | const Unknown = new function() { |
michael@0 | 22 | function hasInterface(component, iid) { |
michael@0 | 23 | return component && component.interfaces && |
michael@0 | 24 | ( component.interfaces.some(function(id) iid.equals(Ci[id])) || |
michael@0 | 25 | component.implements.some(function($) hasInterface($, iid)) || |
michael@0 | 26 | hasInterface(Object.getPrototypeOf(component), iid)); |
michael@0 | 27 | } |
michael@0 | 28 | |
michael@0 | 29 | return Class({ |
michael@0 | 30 | /** |
michael@0 | 31 | * The `QueryInterface` method provides runtime type discovery used by XPCOM. |
michael@0 | 32 | * This method return queried instance of `this` if given `iid` is listed in |
michael@0 | 33 | * the `interfaces` property or in equivalent properties of objects in it's |
michael@0 | 34 | * prototype chain. In addition it will look up in the prototypes under |
michael@0 | 35 | * `implements` array property, this ways compositions made via `Class` |
michael@0 | 36 | * utility will carry interfaces implemented by composition components. |
michael@0 | 37 | */ |
michael@0 | 38 | QueryInterface: function QueryInterface(iid) { |
michael@0 | 39 | // For some reason there are cases when `iid` is `null`. In such cases we |
michael@0 | 40 | // just return `this`. Otherwise we verify that component implements given |
michael@0 | 41 | // `iid` interface. This will be no longer necessary once Bug 748003 is |
michael@0 | 42 | // fixed. |
michael@0 | 43 | if (iid && !hasInterface(this, iid)) |
michael@0 | 44 | throw Cr.NS_ERROR_NO_INTERFACE; |
michael@0 | 45 | |
michael@0 | 46 | return this; |
michael@0 | 47 | }, |
michael@0 | 48 | /** |
michael@0 | 49 | * Array of `XPCOM` interfaces (as strings) implemented by this component. |
michael@0 | 50 | * All components implement `nsISupports` by default which is default value |
michael@0 | 51 | * here. Provide array of interfaces implemented by an object when |
michael@0 | 52 | * extending, to append them to this list (Please note that there is no |
michael@0 | 53 | * need to repeat interfaces implemented by super as they will be added |
michael@0 | 54 | * automatically). |
michael@0 | 55 | */ |
michael@0 | 56 | interfaces: Object.freeze([ 'nsISupports' ]) |
michael@0 | 57 | }); |
michael@0 | 58 | } |
michael@0 | 59 | exports.Unknown = Unknown; |
michael@0 | 60 | |
michael@0 | 61 | // Base exemplar for creating instances implementing `nsIFactory` interface, |
michael@0 | 62 | // that maybe registered into runtime via `register` function. Instances of |
michael@0 | 63 | // this factory create instances of enclosed component on `createInstance`. |
michael@0 | 64 | const Factory = Class({ |
michael@0 | 65 | extends: Unknown, |
michael@0 | 66 | interfaces: [ 'nsIFactory' ], |
michael@0 | 67 | /** |
michael@0 | 68 | * All the descendants will get auto generated `id` (also known as `classID` |
michael@0 | 69 | * in XPCOM world) unless one is manually provided. |
michael@0 | 70 | */ |
michael@0 | 71 | get id() { throw Error('Factory must implement `id` property') }, |
michael@0 | 72 | /** |
michael@0 | 73 | * XPCOM `contractID` may optionally be provided to associate this factory |
michael@0 | 74 | * with it. `contract` is a unique string that has a following format: |
michael@0 | 75 | * '@vendor.com/unique/id;1'. |
michael@0 | 76 | */ |
michael@0 | 77 | contract: null, |
michael@0 | 78 | /** |
michael@0 | 79 | * Class description that is being registered. This value is intended as a |
michael@0 | 80 | * human-readable description for the given class and does not needs to be |
michael@0 | 81 | * globally unique. |
michael@0 | 82 | */ |
michael@0 | 83 | description: 'Jetpack generated factory', |
michael@0 | 84 | /** |
michael@0 | 85 | * This method is required by `nsIFactory` interfaces, but as in most |
michael@0 | 86 | * implementations it does nothing interesting. |
michael@0 | 87 | */ |
michael@0 | 88 | lockFactory: function lockFactory(lock) undefined, |
michael@0 | 89 | /** |
michael@0 | 90 | * If property is `true` XPCOM service / factory will be registered |
michael@0 | 91 | * automatically on creation. |
michael@0 | 92 | */ |
michael@0 | 93 | register: true, |
michael@0 | 94 | /** |
michael@0 | 95 | * If property is `true` XPCOM factory will be unregistered prior to add-on |
michael@0 | 96 | * unload. |
michael@0 | 97 | */ |
michael@0 | 98 | unregister: true, |
michael@0 | 99 | /** |
michael@0 | 100 | * Method is called on `Service.new(options)` passing given `options` to |
michael@0 | 101 | * it. Options is expected to have `component` property holding XPCOM |
michael@0 | 102 | * component implementation typically decedent of `Unknown` or any custom |
michael@0 | 103 | * implementation with a `new` method and optional `register`, `unregister` |
michael@0 | 104 | * flags. Unless `register` is `false` Service / Factory will be |
michael@0 | 105 | * automatically registered. Unless `unregister` is `false` component will |
michael@0 | 106 | * be automatically unregistered on add-on unload. |
michael@0 | 107 | */ |
michael@0 | 108 | initialize: function initialize(options) { |
michael@0 | 109 | merge(this, { |
michael@0 | 110 | id: 'id' in options ? options.id : uuid(), |
michael@0 | 111 | register: 'register' in options ? options.register : this.register, |
michael@0 | 112 | unregister: 'unregister' in options ? options.unregister : this.unregister, |
michael@0 | 113 | contract: 'contract' in options ? options.contract : null, |
michael@0 | 114 | Component: options.Component |
michael@0 | 115 | }); |
michael@0 | 116 | |
michael@0 | 117 | // If service / factory has auto registration enabled then register. |
michael@0 | 118 | if (this.register) |
michael@0 | 119 | register(this); |
michael@0 | 120 | }, |
michael@0 | 121 | /** |
michael@0 | 122 | * Creates an instance of the class associated with this factory. |
michael@0 | 123 | */ |
michael@0 | 124 | createInstance: function createInstance(outer, iid) { |
michael@0 | 125 | try { |
michael@0 | 126 | if (outer) |
michael@0 | 127 | throw Cr.NS_ERROR_NO_AGGREGATION; |
michael@0 | 128 | return this.create().QueryInterface(iid); |
michael@0 | 129 | } |
michael@0 | 130 | catch (error) { |
michael@0 | 131 | throw error instanceof Ci.nsIException ? error : Cr.NS_ERROR_FAILURE; |
michael@0 | 132 | } |
michael@0 | 133 | }, |
michael@0 | 134 | create: function create() this.Component() |
michael@0 | 135 | }); |
michael@0 | 136 | exports.Factory = Factory; |
michael@0 | 137 | |
michael@0 | 138 | // Exemplar for creating services that implement `nsIFactory` interface, that |
michael@0 | 139 | // can be registered into runtime via call to `register`. This services return |
michael@0 | 140 | // enclosed `component` on `getService`. |
michael@0 | 141 | const Service = Class({ |
michael@0 | 142 | extends: Factory, |
michael@0 | 143 | initialize: function initialize(options) { |
michael@0 | 144 | this.component = options.Component(); |
michael@0 | 145 | Factory.prototype.initialize.call(this, options); |
michael@0 | 146 | }, |
michael@0 | 147 | description: 'Jetpack generated service', |
michael@0 | 148 | /** |
michael@0 | 149 | * Creates an instance of the class associated with this factory. |
michael@0 | 150 | */ |
michael@0 | 151 | create: function create() this.component |
michael@0 | 152 | }); |
michael@0 | 153 | exports.Service = Service; |
michael@0 | 154 | |
michael@0 | 155 | function isRegistered({ id }) isCIDRegistered(id) |
michael@0 | 156 | exports.isRegistered = isRegistered; |
michael@0 | 157 | |
michael@0 | 158 | /** |
michael@0 | 159 | * Registers given `component` object to be used to instantiate a particular |
michael@0 | 160 | * class identified by `component.id`, and creates an association of class |
michael@0 | 161 | * name and `component.contract` with the class. |
michael@0 | 162 | */ |
michael@0 | 163 | function register(factory) { |
michael@0 | 164 | if (!(factory instanceof Factory)) { |
michael@0 | 165 | throw new Error("xpcom.register() expect a Factory instance.\n" + |
michael@0 | 166 | "Please refactor your code to new xpcom module if you" + |
michael@0 | 167 | " are repacking an addon from SDK <= 1.5:\n" + |
michael@0 | 168 | "https://addons.mozilla.org/en-US/developers/docs/sdk/latest/packages/api-utils/xpcom.html"); |
michael@0 | 169 | } |
michael@0 | 170 | |
michael@0 | 171 | registerFactory(factory.id, factory.description, factory.contract, factory); |
michael@0 | 172 | |
michael@0 | 173 | if (factory.unregister) |
michael@0 | 174 | require('../system/unload').when(unregister.bind(null, factory)); |
michael@0 | 175 | } |
michael@0 | 176 | exports.register = register; |
michael@0 | 177 | |
michael@0 | 178 | /** |
michael@0 | 179 | * Unregister a factory associated with a particular class identified by |
michael@0 | 180 | * `factory.classID`. |
michael@0 | 181 | */ |
michael@0 | 182 | function unregister(factory) { |
michael@0 | 183 | if (isRegistered(factory)) |
michael@0 | 184 | unregisterFactory(factory.id, factory); |
michael@0 | 185 | } |
michael@0 | 186 | exports.unregister = unregister; |
michael@0 | 187 | |
michael@0 | 188 | function autoRegister(path) { |
michael@0 | 189 | // TODO: This assumes that the url points to a directory |
michael@0 | 190 | // that contains subdirectories corresponding to OS/ABI and then |
michael@0 | 191 | // further subdirectories corresponding to Gecko platform version. |
michael@0 | 192 | // we should probably either behave intelligently here or allow |
michael@0 | 193 | // the caller to pass-in more options if e.g. there aren't |
michael@0 | 194 | // Gecko-specific binaries for a component (which will be the case |
michael@0 | 195 | // if only frozen interfaces are used). |
michael@0 | 196 | |
michael@0 | 197 | var runtime = require("../system/runtime"); |
michael@0 | 198 | var osDirName = runtime.OS + "_" + runtime.XPCOMABI; |
michael@0 | 199 | var platformVersion = require("../system/xul-app").platformVersion.substring(0, 5); |
michael@0 | 200 | |
michael@0 | 201 | var file = Cc['@mozilla.org/file/local;1'] |
michael@0 | 202 | .createInstance(Ci.nsILocalFile); |
michael@0 | 203 | file.initWithPath(path); |
michael@0 | 204 | file.append(osDirName); |
michael@0 | 205 | file.append(platformVersion); |
michael@0 | 206 | |
michael@0 | 207 | if (!(file.exists() && file.isDirectory())) |
michael@0 | 208 | throw new Error("component not available for OS/ABI " + |
michael@0 | 209 | osDirName + " and platform " + platformVersion); |
michael@0 | 210 | |
michael@0 | 211 | Cm.QueryInterface(Ci.nsIComponentRegistrar); |
michael@0 | 212 | Cm.autoRegister(file); |
michael@0 | 213 | } |
michael@0 | 214 | exports.autoRegister = autoRegister; |
michael@0 | 215 | |
michael@0 | 216 | /** |
michael@0 | 217 | * Returns registered factory that has a given `id` or `null` if not found. |
michael@0 | 218 | */ |
michael@0 | 219 | function factoryByID(id) classesByID[id] || null |
michael@0 | 220 | exports.factoryByID = factoryByID; |
michael@0 | 221 | |
michael@0 | 222 | /** |
michael@0 | 223 | * Returns factory registered with a given `contract` or `null` if not found. |
michael@0 | 224 | * In contrast to `Cc[contract]` that does ignores new factory registration |
michael@0 | 225 | * with a given `contract` this will return a factory currently associated |
michael@0 | 226 | * with a `contract`. |
michael@0 | 227 | */ |
michael@0 | 228 | function factoryByContract(contract) factoryByID(Cm.contractIDToCID(contract)) |
michael@0 | 229 | exports.factoryByContract = factoryByContract; |