2

我们正在尝试构建一个 Firefox 扩展,其中我们的扩展将包含许多 Javascript 插件。此处的插件被定义为一组具有主入口点的函数,它们通常提供响应。在 OOP 中,它们将共享相同的公共抽象类,并且可以预见 $obj->init()->run()->get() 链。

它们将是一个插件池,每个插件都应该有一个排名,插件的执行应该基于它们的排名。

主要问题是:
- 你如何在裸 Javascript 中创建插件系统
- 它们是 JS 中可用于启动的任何开源插件系统
- 你将如何存储插件池系统及其排名,以及
- 如何存储您确保插件按其排名顺序执行

4

1 回答 1

3

你的问题真的很模糊,所以我将根据一堆猜测来回答。您可能想做一些类似于Add-on SDK在内部所做的事情 - 将您的插件加载到沙箱中,为它们提供一些 API 并根据需要调用它们的方法。另外,我猜您想使用null 主体来确保沙箱没有额外的权限。这样的事情应该做:

Components.utils.import("resource://gre/modules/Services.jsm");

var sandboxProto = {
  rank: -1,
  foo: function()
  {
    throw new Error("Please implement");
  },
  myAPIMethod: function()
  {
    return 5;
  }
};
var sandboxPrincipal = Components.classes["@mozilla.org/nullprincipal;1"]
                         .getService(Components.interfaces.nsIPrincipal);

var plugins = [];

function loadPlugin(url)
{
  try
  {
    var sandbox = Components.utils.Sandbox(sandboxPrincipal, {
      sandboxName: url,
      sandboxPrototype: sandboxProto
    });
    Services.scriptloader.loadSubScript(url, sandbox);
    plugins.push(sandbox);
  }
  catch (e)
  {
    Components.utils.reportError(e);
  }
}

function callPluginMethod(methodName)
{
  var args = Array.prototype.slice.call(arguments, 1);

  // Always resort plugins in case their rank changes
  plugins.sort(function(a, b)
  {
    // Make sure that we work with numbers
    var r1 = parseInt(a.rank, 10) || -1;
    var r2 = parseInt(a.rank, 10) || -1;
    return r2 - r1;
  });

  var results = [];
  for (var i = 0; i < plugins.length; i++)
  {
    if (methodName in plugins[i])
    {
      try
      {
        results.push(plugins[i][methodName].apply(plugins[i], args));
      }
      catch (e)
      {
        Components.utils.reportError(e);
      }
    }
  }
  return results;
}

一个插件看起来像这样:

var rank = 1000;

function foo()
{
  return 2 * myAPIMethod();
}

所以下面的代码应该告诉你[10]

loadPlugin("chrome://.../content/plugin.js");

var results = callPluginMethod("foo");
alert(results.toSource());

至于您的扩展如何知道在哪里可以找到它的插件 - 这是一个完全不同的问题,很大程度上取决于要求(这个问题中缺少的东西)。但是请注意,下标加载器仅适用于本地 URL - 只有作为扩展程序的一部分或位于用户磁盘上的插件才能使用。如果插件列表是动态的,那么您可能希望在用户配置文件中为它们创建一个目录并根据需要将它们下载到该目录(您应该非常小心,不要给这些插件太多权限,以避免安全问题)。

于 2012-05-29T07:37:58.720 回答