我怎样才能使 firefox 附加内容脚本在其他页面脚本之前注入和 运行 脚本?
How can I make a firefox add-on contentscript inject and run a script before other page scripts?
我正在开发浏览器 extension/add-on。我们在 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 步 运行 顺序不确定。
非常感谢!
我在特殊分支的 public 存储库中有与 Firefox 兼容的脚本版本,如果您敢于自己尝试的话:https://github.com/MetaMask/metamask-plugin/tree/FirefoxCompatibility
具有外部源 (<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();
如果您使用的是基于 bootstrap.js 的插件,您可以使用框架脚本和 DOMWindowCreated
在 HTML DOM(过去的基础知识document.body 等)呈现 - https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment#Events - 内部 HTML 将可用,但不会执行任何脚本。如@Rob 所述,您可以将内联脚本放在顶部。
我正在开发浏览器 extension/add-on。我们在 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 步 运行 顺序不确定。
非常感谢!
我在特殊分支的 public 存储库中有与 Firefox 兼容的脚本版本,如果您敢于自己尝试的话:https://github.com/MetaMask/metamask-plugin/tree/FirefoxCompatibility
具有外部源 (<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();
如果您使用的是基于 bootstrap.js 的插件,您可以使用框架脚本和 DOMWindowCreated
在 HTML DOM(过去的基础知识document.body 等)呈现 - https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment#Events - 内部 HTML 将可用,但不会执行任何脚本。如@Rob 所述,您可以将内联脚本放在顶部。