5

我有一个 Firefox 的引导扩展。现在我想实现 nsIContentPolicy XPCOM 组件。我写了一个组件模块代码。现在我想注册这个组件。我想注册组件的原因是我想将我的组件添加到 nsICategoryManager.addCategoryEntry“内容策略”类别中。

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]);

问题:

  • 是否可以从引导扩展注册组件?
  • 是否可以从无重启扩展注册组件?
  • 是否可以在没有组件的情况下使用 nsICategoryManager.addCategoryEntry "content-policy"?
  • 如何在引导扩展中注册组件或以某种方式添加新的“内容策略”类别条目?

我已添加到harness-options.js

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

这就是我尝试导入模块的方式:

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

我尝试了很多方法)))但没有一个有效。chrome.manifest 文件中的资源条目不允许引导扩展。组件模块文件的路径为: resources/deferredto/lib/interceptor.js

4

2 回答 2

3

现在我nsIContentPolicy的基于 sdk 的组件看起来像这样。文件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);

您可以像这样从 sdk 使用它:

var interceptor = require("./interceptor");
于 2013-09-01T00:53:23.373 回答
3

Adblock Plus 无需重新启动但不使用 SDK,它在运行时注册一个nsIContentPolicy实现,就像您的 SDK 一样。可能有一些 SDK 附加组件在运行时注册组件,但我不知道有什么开源的,我会建议您立即查看。

关于 ABP 实现的几点说明以及为了使其与 SDK 一起工作而需要进行的更改:

  • 类别管理器可通过 获得Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager)
  • 组件注册器应该也可以通过componentschrome模块中要求获得,然后components.manager.getService(Ci.nsIComponentRegistrar).
  • 作为 Adblock Plus,您必须自己在 unload 上注销您的组件。
  • 不幸的是,卸载部分也有点欺骗,因为由于错误 753687,您无法同步取消注册组件和类别条目。因此,Adblock Plus 使用 异步执行它Util.runAsync,它只是将一个可运行的(事件,如果你喜欢)分派到主线程。我不认为你可以在这里使用任何 SDK 的东西,因为 SDK 会在任何异步代码有机会运行之前清理,所以你需要自己使用低级 XPCOM 可运行(或计时器)。
  • 您的代码将在运行时注册您的组件。你不会触摸harness-options或类似的东西。

(我自己也实现了一个通用的组件注册功能,但这又不是 SDK 代码,需要适应在 SDK 中运行,就像 ABP 一样。它也与 ABP 非常相似。)

于 2013-08-21T19:55:13.867 回答