Firefox addon 如何使firefox附加组件contentscript在其他页面脚本之前插入并运行脚本?

Firefox addon 如何使firefox附加组件contentscript在其他页面脚本之前插入并运行脚本?,firefox-addon,content-script,firefox-addon-webextensions,Firefox Addon,Content Script,Firefox Addon Webextensions,我正在开发浏览器扩展/附加组件。我们已经在Chrome上运行了,所以我正在努力让它在Firefox上运行 我已经在Firefox开发者版49.0a2(2016-07-25)中加载了我的插件 我的扩展包括一个content_脚本,设置为run_at:document_start,这样它可以在其他页面脚本运行之前插入一个脚本标记,这样它就可以使一个对象对网站全局可用 这在Chrome中似乎很好,但在Firefox中,它被证明是一种竞争条件,大多数情况下其他页面资源首先加载 是否有一种加载内容脚本的策

我正在开发浏览器扩展/附加组件。我们已经在Chrome上运行了,所以我正在努力让它在Firefox上运行

我已经在Firefox开发者版49.0a2(2016-07-25)中加载了我的插件

我的扩展包括一个content_脚本,设置为
run_at:document_start
,这样它可以在其他页面脚本运行之前插入一个脚本标记,这样它就可以使一个对象对网站全局可用

这在Chrome中似乎很好,但在Firefox中,它被证明是一种竞争条件,大多数情况下其他页面资源首先加载

是否有一种加载内容脚本的策略,它可以在任何其他页面脚本运行之前注入并加载脚本

当我添加日志时,我可以很好地隔离正在发生的事情。在此示例内容脚本中:

// inject in-page script
console.log('STEP 1, this always happens first')
var scriptTag = document.createElement('script')
scriptTag.src = chrome.extension.getURL('scripts/inpage.js')
scriptTag.onload = function () { this.parentNode.removeChild(this) }
var container = document.head || document.documentElement
// append as first child
container.insertBefore(scriptTag, container.children[0])
现在,如果文件
scripts/inpage.js
只是运行一个日志,比如

console.log('STEP 2, this should always run second')
我访问了一个页面,上面有这样一个脚本:

console.log('Step 3, the page itself, should run last')
实际上,步骤2和步骤3以不确定的顺序运行

非常感谢


我在一个特殊分支的公共存储库中有一个与Firefox兼容的脚本版本,如果你敢亲自尝试的话:

一个带有外部源(
)的动态插入脚本不会阻止脚本的执行,因此不能保证你的脚本会被加载。如果你的扩展在Chrome上工作,那纯粹是运气使然

如果您确实想在其他脚本之前运行某些脚本,则必须以内联方式运行它:

var实际代码=`
//此处是scripts/inpage.js的内容
`;
var s=document.createElement('script');
s、 text内容=实际代码;
(document.head | | document.documentElement)。追加子项;
s、 删除();
理想情况下,构建脚本将读取
scripts/inpage.js
,将其序列化为字符串并将其放入
actualCode
变量中。但是如果
inpage.js
只是几行代码,那么可以使用上面的代码

请注意,除非绝对必要,否则不应在网页中插入代码。原因是页面的执行环境不可信。如果在
document\u start
处注入,则可以保存稍后(在闭包中)使用的函数和(原型)方法,但需要非常仔细的编码

如果您的内容脚本不是由生成脚本生成的,并且您仍然希望将脚本分开,那么您还可以使用synchronous
XMLHttpRequest
获取脚本。出于性能原因,不推荐使用同步XHR,因此使用同步XHR的风险自负。扩展代码通常与您的扩展捆绑在一起,因此使用同步xhr应该是低风险的:

//注意:不要在生产中使用同步XHR!
var x=新的XMLHttpRequest();
x、 open('GET',chrome.runtime.getURL('scripts/inpage.js'),false);
x、 send();
var actualCode=x.responseText;
var s=document.createElement('script');
s、 text内容=实际代码;
(document.head | | document.documentElement)。追加子项;
s、 删除();

如果您使用的是基于bootstrap.js的加载项,则可以在HTML DOM(document.body等的过去基础知识)呈现之前使用framescript和
DOMWindowCreated
来处理文档--innerHTML将可用,但不会执行任何脚本。您可以将内联脚本放在顶部,如@Rob所述。

这是我在当前页面中预先添加脚本标记的那一行。当我使用日志执行此操作时,我确实看到此代码在页面脚本之前运行,但是注入的脚本本身并不总是在页面脚本之前运行。我只想补充一点,在IRC中,您还指出FireFox提供了额外的方法,可以通过导出帮助程序将API从contentscript公开到主页面:尚未提供@DanF
Component.utils.exportFunction
等(并且它们在
组件
命名空间中不可用;WebExtensions不能使用
组件
)。当补丁到达时,您可以使用全局
导出函数
方法获得相同的功能。