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.

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

mercurial