Firefox扩展中的ContentScript,不使用附加SDK

时间:2014-06-13 09:35:44

标签: javascript firefox firefox-addon content-script

是否有一种简单的方法可以为简单的内容脚本创建Firefox扩展,而无需使用Add-On SDK和PageMod?通过安装Python和SDK的麻烦,学习如何使用SDK和API,添加不必要的膨胀和抽象层,只是为了执行一个简单的内容脚本,这似乎有点过头了。

我已经尝试过使用XUL浏览器覆盖并在那里注入脚本,但是在browser.xul上下文而不是document.body中注入所有内容也会增加很多复杂性......

那么在html文档而不是XUL文档中注入一些脚本和css文件最简单,最轻量级的方法是什么?

1 个答案:

答案 0 :(得分:7)

你的猜测是边界过于宽泛,所以我不会详细讨论所有内容,但会给出一般概述。

简单可能是夸大其词,但SDK内容脚本(实际上也是模块),Greasemonkey / Scriptish以及其他类似于内容脚本的内容在内部使用Sandbox。即使bootstrap.js在无重新启动的附加组件中也会在沙盒中执行。

基本思路如下:

  1. 获取您要附加的内容窗口的引用。
  2. 选择"校长"脚本应该运行在。委托人本质上是安全上下文/政策,也定义了相同的起源。非特权内容脚本通常使用内容窗口本身(也是主体),而特权脚本(对Components的访问权限)脚本将使用系统主体。
  3. 选择是否需要XRay包装器。文档会告诉你更多相关信息。
  4. 选择Sandbox原型("全球"或顶级)。通常,对于内容脚本,您可以选择内容窗口。
  5. 创建Sandbox
  6. 将您的内容脚本可能需要的任何内容添加到沙盒中。
  7. 执行evalInSandboxsubscript loader
  8. 的脚本

    以下是向窗口添加非特权内容脚本的有限示例:

    // 1. get the content window, e.g. the currently selected tab window
    var contentWindow = gBrowser.contentWindow;
    // 2. Choose the principal, e.g. just use the content window again
    var principal = contentWindow;
    // 3. We want XRay wrappers, to keep our content script and the actual
    // page scripts in their own corners.
    var wantXrays = true;
    // 4. Our prototype will be the window
    var sbProto = contentWindow;
    // 5. Putting it all together to create a sandbox
    var sandbox = Cu.Sandbox(principal, {
      sandboxPrototype: sbProto,
      wantXrays: wantXrays
    });
    // 6. Adding a random helper function (e.g.)
    sandbox.getRandomInt = function (min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    };
    // 7. Execute some content script, aka. the stupid example.
    try {
      var execute = function() {
        var demo1 = document.querySelector('title').textContent;
        var demo2 = getRandomInt(1, 1000);
        alert(demo1 + " " + demo2);
      }
      Cu.evalInSandbox(
        "(" + execute.toSource() + ")()",
        sandbox
      );
    } catch(ex) {
      console.error(ex);
    }
    

    PS:此示例将在Scratchpad with Environment/Browser中逐字运行。

    关于样式:

    执行SDK的功能,我想,这是简化的:

    var wu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
             getInterface(Ci.nsIDOMWindowUtils);
    var uri = Services.io.newURI(
      "chrome://myaddon/style/content-style.css",
      null,
      null);
    wu.loadSheet(uri, wu.USER_SHEET);