2012-05-28 32 views
2

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

他们将是一个插件池,每个插件应该有一个等级,插件的执行应该根据他们的等级执行。

的主要问题是:
- 你怎么在裸露的Javascript
创建一个插件系统 - 它们是任何开源的JS插件系统,其可用于启动
- 你将如何存储插件池系统和自己的排名,并
- 你将如何确保该插件在其排名的顺序执行

+0

我想你想要你的插件被沙盒,而不是有全部的特权? –

+0

@WladimirPalant在这个阶段,我并不在意沙盒,因为在初始阶段,我将是唯一的开发人员,但是我需要创意。正如我看到你是这方面的专家。你能分享一些答案吗? – Pentium10

回答

3

你的问题实在是模糊的,所以我会根据一堆猜测来回答吧。您可能想要执行类似Add-on SDK内部的操作 - 将您的插件加载到sandboxes中,为它们提供一些API并根据需要调用它们的方法。另外,我想你想使用null principal来确保沙盒没有额外的权限。像这样的东西应该做的:

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一起工作 - 只有插件可以作为您的扩展的一部分或位于用户磁盘上。如果插件列表将是动态的,那么您可能需要在用户配置文件中为它们创建一个目录,并根据需要将它们下载到此目录中(您应该非常小心,因为不要为这些插件提供太多权限,安全问题)。

+0

谢谢你,这是一个很大的帮助。 – Pentium10

+0

我们也将在服务器端提供这些插件,实际上他们对DOM对象做了一些事情。我们想知道是否可以通过在Node.JS中拥有服务器端组件来实现代码重用。据您所知,可以从扩展中获取某些Javascript对象并放置在不同的JS服务器中,并且都具有相同的功能? – Pentium10

+0

只要访问的API存在于客户端和服务器上,他们当然可以。根据CommonJS,在客户端提供'require()'函数可能是最简单的。但这是一个非常微不足道的事情来实现。 –