How to implement XPCOM component (nsIContentPolicy) in bootstrapped Firefox extension

旧巷老猫 提交于 2020-01-01 11:37:07

问题


I have a bootstrapped extension for Firefox. And now I want to implement nsIContentPolicy XPCOM component. I wrote a component module code. And now I want to register this component. The reason I want to register component is that I want to add my component to nsICategoryManager.addCategoryEntry with "content-policy" category.

var {Cc, Ci, Cu} = require("chrome");

Cu.import("resource://gre/modules/XPCOMUtils.jsm");

//console.error("Running interceptor");

function Interceptor() 
}

Interceptor.prototype = {

    classDescription: "DeferredTo HTTP requests Interceptor",
    classID: "{B5B3D9A0-08FC-11E3-8253-5EF06188709B}",
    contractID: "@deferredto.com/Interceptor;1",
    QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy]),

    shouldLoad : function dt_shouldLoad(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) {
        console.log("dt_shouldLoad");

        if (contentLocation.scheme != "http" && contentLocation.scheme != "https")
            return Ci.nsIContentPolicy.ACCEPT;

        let result = Ci.nsIContentPolicy.ACCEPT;

        // we should check for TYPE_SUBDOCUMENT as well if we want frames.
        if ((Ci.nsIContentPolicy.TYPE_DOCUMENT == aContentType) &&
            SOME_REGULAR_EXPRESSION.test(aContentLocation.spec)) {
            // do stuff here, possibly changing result.
        }
        return result;
    },

    shouldProcess: function ILO_shouldProcess() Ci.nsIContentPolicy.ACCEPT,

    _xpcom_categories: [
        { category: "content-policy", service: true }
    ],
    classInfo: XPCOMUtils.generateCI(
    {classID: Components.ID("{B5B3D9A0-08FC-11E3-8253-5EF06188709B}"),
     contractID: "@deferredto.com/Interceptor;1",
     classDescription: "Interceptor implements nsIContentPolicy to block images that are not yet at screen @DeferredTo",
     interfaces: [
                  Ci.nsIContentPolicy,
                  ],
     flags: Ci.nsIClassInfo.SINGLETON})
}

var components = [Interceptor];

var NSGetFactory = XPCOMUtils.generateNSGetFactory([Interceptor]);

Questions:

  • Is it possible to register the component from bootstrapped extension?
  • Is it possible to register the component from restartless extension?
  • Is it possible to use nsICategoryManager.addCategoryEntry "content-policy" without component?
  • How to register the component in bootstrapped extension or somehow add new "content-policy" category entry?

I've added to harness-options.js

"requirements": {
"sdk/page-mod": "sdk/page-mod",
"sdk/self": "sdk/self",
"chrome": "chrome"},

That is how I try to import module:

var {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://deferredto/lib/interceptor.js");

I' ve tried many paths ))) But none works. resource entry in chrome.manifest file does not allowed for bootstrapped extensions. The path to component module file is: resources/deferredto/lib/interceptor.js


回答1:


Adblock Plus, which is restartless but not using the SDK, registers an nsIContentPolicy implementation at runtime, just like your SDK would. There are probably a few SDK add-ons registering components at run time, but I don't know any open source ones that I would recommend to look at off the top of my head.

A few points regarding that ABP implementation and what to change to make it work with the SDK:

  • The category manager is available via Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager).
  • The component registrar should be available by requiring also components from the chrome module and then components.manager.getService(Ci.nsIComponentRegistrar).
  • As Adblock Plus, you must unregister your component yourself on unload.
  • The unload part is unfortunely also a bit tricking, since you cannot synchronously unregister your component and the category entry, due to Bug 753687. Adblock Plus therefore does it async using Util.runAsync, which just dispatches a runnable (event, if you like) to the main thread. I don't think you can use any SDK stuff here, as the SDK will clean up before any async code gets a chance to run, so you'd need to use a low-level XPCOM runnable (or timer) yourself.
  • Your code will register your component at runtime. You won't touch harness-options or anything like that.

(I also implemented a generic component register function myself, but that again is not SDK code, and would need to be adapted to run in the SDK, just like the ABP one. It is also very similar to the ABP one.)




回答2:


Now my nsIContentPolicy sdk-based component look like this. File interceptor.js:

'use strict';

var { Class } = require('sdk/core/heritage');
var xpcom = require('sdk/platform/xpcom');
var { Cc, Ci, Cu, Cm } = require('chrome');
var categoryManager = Cc["@mozilla.org/categorymanager;1"]
                      .getService(Ci.nsICategoryManager);


// nsIDOMNode
const TYPE_DOCUMENT_NODE        = Ci.nsIDOMNode.DOCUMENT_NODE;


/// Interceptor


var contractId = "@deferredto.com/Interceptor;1";

var Interceptor = Class({
  extends:  xpcom.Unknown,
  interfaces: [ 'nsIContentPolicy' ],
  get wrappedJSObject() this,

  shouldLoad : function dt_shouldLoad(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) {

        let result = Ci.nsIContentPolicy.ACCEPT;

        return result;
    },

    shouldProcess: function () Ci.nsIContentPolicy.ACCEPT
});

var factory = xpcom.Factory({
  contract: contractId,
  Component: Interceptor,
  unregister: false // see https://bugzilla.mozilla.org/show_bug.cgi?id=753687
});

/// unload 
var unload = require("sdk/system/unload");

unload.when(function() {
  function trueUnregister() {
    categoryManager.deleteCategoryEntry("content-policy", contractId, false);
    try {
      console.log("xpcom.isRegistered(factory)="  + xpcom.isRegistered(factory));
      console.log("trueUnregister");
      xpcom.unregister(factory);
      console.log("xpcom.isRegistered(factory)="  + xpcom.isRegistered(factory));
    } catch (ex) {
        Cu.reportError(ex);
    }      
  }
  if ("dispatch" in Cu) {
    console.log('"dispatch" in Cu');
    Cu.dispatch(trueUnregister, trueUnregister);
  } else {
    console.log('"dispatch" not! in Cu');
    Cu.import("resource://gre/modules/Services.jsm");
    Services.tm.mainThread.dispatch(trueUnregister, 0);
  }
});


//xpcom.register(factory);

var interceptor = Cc[contractId].createInstance(Ci.nsIContentPolicy);

categoryManager.deleteCategoryEntry("content-policy", contractId, false);
categoryManager.addCategoryEntry("content-policy", contractId, contractId, false, true);

And you can use it from sdk like this:

var interceptor = require("./interceptor");


来源:https://stackoverflow.com/questions/18354668/how-to-implement-xpcom-component-nsicontentpolicy-in-bootstrapped-firefox-exte

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!