从firefox附加内容脚本加载其他javascript代码

时间:2013-10-21 00:49:43

标签: firefox-addon

我正在编写一些我想要发布的内容作为chrome扩展和firefox附加组件。

Chrome扩展程序为already available on github。我使用类似于requirejs使用的模块加载格式将我的代码分解为几个模块;我这样做是为了将特定于chrome的部分与我希望在firefox附加组件中重复使用的部分分开。

具体来说,我不仅拆分了后端工作,还拆分了内容脚本。

在chrome中,当我的内容脚本需要加载另一个模块时,它会向后台页面发送一条消息,说“请加载此模块”;然后在后台页面上的脚本执行:

  function onLoadLibrary(request, sender, sendResponse) { 
    var allFrames = request.allFrames || false;
    chrome.tabs.executeScript(
      sender.tab.id, {file: request.library.toLowerCase()  + '.js',
                      allFrames: allFrames},
      function () {
        sendResponse({});
      });
    return true;
  }

也就是说,我可以将其他javascript加载到与要求该代码的内容脚本相同的沙箱中。这对于使模块依赖性起作用是必要的。

在firefox中,我无法弄清楚如何做到这一点。我将通过pageMod附加我的初始内容脚本,并通过tab.attach的“就绪”事件调用tabs。这看起来很简单,但如果内容脚本需要加载更多代码,我就看不出怎么做了。

似乎没有办法从main.js文件访问我的内容脚本运行的沙箱,以便我可以向其中注入更多代码。即使我以某种方式保留了对相关tab实例的引用(在任何情况下只让我注入顶部框架),似乎每次对tab.attach的新调用都会将注入的代码放入新的沙箱中。传递给我的ready事件句柄的对象tab不是我可以传递给require("tabs/util").getBrowserForTab的真实XUL选项卡;如果是,那么我认为我可以通过足够的sdk代码来创建我自己的沙箱,但我担心会留下意外的内存泄漏。

我考虑过通过“eval-this-code”消息将代码传回内容脚本,但出于安全考虑,我真的不想在我的扩展中使用eval;我还担心使用eval会使我很难无法获得AMO批准的firefox附加组件。 (另外,当我的附加组件在具有内容安全策略的网站上运行时,它会如何交互?)

使用traits来定义附加API似乎会关闭对象的访问权限,以至于无法访问Worker以获取对沙箱的引用我的内容脚本是在这一点上,我似乎需要在我的附加组件中包含几乎完整的sdk副本,以便在WorkerSandbox上公开一个方法。

注意:我正在使用Add-On sdk(以前称为JetPack的项目)。如果有人可以告诉我如何在Add-On SDK管理的内容脚本中使用它,我愿意使用Components.utils.import

1 个答案:

答案 0 :(得分:1)

内容脚本在初始化后不公开公共API以将更多脚本附加到内容脚本沙箱。你应该提交enhancement bug并说明你的用例,如果没有一个已经提交(先搜索),和/或甚至是自己come up with some patches

如果您的加载项拥有一个DOM(widget),那么只需附加另一个脚本标记即可。

对于像page-mods这样没有你拥有的DOM的东西,你会留下一些选项,其中没有一个真的令人满意。正如您已经发现的那样,使用特征会禁止您访问“私人”属性/方法。

  • 分叉page-mod / tab / content-worker以提供您需要的功能。这需要创建自己的模块副本并公开必要的API以将脚本注入现有工作者。

    这是一个陡峭的学习曲线(但考虑到你已经找出了特征等细节,应该对你有用),但更重要的是难以维护,因为你需要确保跟上上游。 AMO编辑不会非常喜欢你:p

    从好的方面来说,你可以尝试让你的东西上传,为每个人解决这个问题,并成为使用附加SDK的许多作者的英雄。

  • 您提出的eval方法。这eval不仅是安全问题的主要来源,而且也可能是性能杀手,因为现在IIRC eval ed代码不会使用JIT。而且,当然,即使使用“正确”,它也会让AMO编辑感到畏缩。

  • 根本不要使用延迟加载,并从一开始就指定所有内容脚本。这是附加组件通常所做的事情(我几乎倾向于说“永远”)。但是,这与您当前的设计存在冲突,并且根据您的附加组件可能会对加载最终不需要的内容造成严重的性能损失。

  • 您可以使用require机制将大多数脚本作为SDK模块而不是内容脚本。当然,这并不总是可行的,例如,处理通常会修改内容脚本中的DOM的代码,但可能适用于其他一些东西。

  • 使用您自己的类似Greasemonkey的增强型API替换page-mod等。这意味着许多工作,它容易出错,对安全性敏感,必须进行维护。所以,这不是一个真正可行的解决方案,IMO ......

Components.utils.import对您没有帮助。无论如何它都不适用于内容脚本。