addon-sdk/source/lib/sdk/platform/xpcom.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.

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;

mercurial