我正在使用浏览器扩展程序/插件。我们在Chrome中使用它,所以我试图让它在Firefox中运行。
我已经在Firefox Developer Edition 49.0a2(2016-07-25)中加载了我的加载项。
我的扩展涉及将content_script设置为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兼容的脚本版本:https://github.com/MetaMask/metamask-plugin/tree/FirefoxCompatibility
答案 0 :(得分:4)
带有外部源(<script src>
)的动态插入脚本不会阻止脚本的执行,因此无法保证您的脚本会加载。如果您的扩展程序在Chrome中运行,那只是纯粹的运气。
如果你真的想在其余的脚本之前运行一些脚本,你必须以内联方式运行它:
var actualCode = `
// Content of scripts/inpage.js here
`;
var s = document.createElement('script');
s.textContent = actualCode;
(document.head || document.documentElement).appendChild(s);
s.remove();
理想情况下,您的构建脚本会读取scripts/inpage.js
,将其序列化为字符串并将其放入actualCode
变量中。但如果inpage.js
只是几行代码,则可以使用上述代码。
请注意,不应在网页中注入代码,除非绝对必要。原因是页面的执行环境是不可信的。如果你注入document_start
,那么你可以保存稍后用于(在闭包中)的函数和(原型)方法,但是需要非常仔细的编码。
如果您的内容脚本不是由构建脚本生成的,并且您仍希望将脚本分开,那么您也可以使用同步XMLHttpRequest
来获取脚本。出于性能原因,不推荐使用同步XHR,因此使用它需要您自担风险。扩展代码通常与您的扩展程序捆绑在一起,因此使用sync xhr应该是低风险的:
// Note: do not use synchronous XHR in production!
var x = new XMLHttpRequest();
x.open('GET', chrome.runtime.getURL('scripts/inpage.js'), false);
x.send();
var actualCode = x.responseText;
var s = document.createElement('script');
s.textContent = actualCode;
(document.head || document.documentElement).appendChild(s);
s.remove();
答案 1 :(得分:0)
如果您使用的是基于bootstrap.js的插件,则可以使用framescript和DOMWindowCreated
来处理文档,甚至在HTML DOM(以前的document.body等基础知识)呈现之前 - https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment#Events - innerHTML将可用,但不会执行任何脚本。您可以将内联脚本放在@Rob提到的顶部。