我正在开发Chrome扩展程序.我没有使用manifest.json
匹配所有URL的内容脚本,而是chrome.tabs.executeScript
在用户单击扩展图标时通过调用来懒惰地注入内容脚本.
我正在尝试的是避免多次执行脚本.所以我在我的内容脚本中有以下代码:
if (!window.ALREADY_INJECTED_FLAG) {
window.ALREADY_INJECTED_FLAG = true
init() // <- All side effects go here
}
问题#1,chrome.tabs.executeScript
每次点击扩展图标时这是否足够安全?换句话说,这是幂等的吗?
问题#2,是否有类似的方法chrome.tabs.insertCSS
?
似乎无法在backgroud脚本中检查内容脚本注入状态,因为它无法访问网页的DOM.我已经尝试了ping/pong方法来检查任何内容脚本实例是否存活.但这会带来设计ping超时的开销和复杂性.
问题#3,任何更好的后台脚本方法来检查内容脚本的注入状态,所以我可以阻止chrome.tabs.executeScript
每次用户点击图标时调用?
提前致谢!
chrome.tabs.executeScript
每次点击扩展图标时,这是否足够安全?换句话说,这是幂等的吗?
是的,除非您的内容脚本修改了页面的DOM并且重新加载了扩展名(通过设置页面重新加载,通过更新等).在这种情况下,旧的内容脚本将不再在扩展的上下文中运行,因此它不能使用扩展API,也不能直接与您的扩展通信.
是否有类似的方法
chrome.tabs.insertCSS
?
不,没有任何包容性的保护chrome.tabs.insertCSS
.但是再次插入相同的样式表并不会改变页面的外观,因为所有规则都具有相同的CSS特性,并且在这种情况下最后一个样式表优先.但是如果样式表与您的扩展名紧密耦合,那么您只需使用executeScript注入脚本,检查它是否是第一次注入,如果是,请插入样式表(参见下面的示例).
任何更好的后台脚本方法来检查内容脚本的注入状态,所以我可以阻止
chrome.tabs.executeScript
每次用户点击图标时调用 ?
您可以向tab(chrome.tabs.sendMessage
)发送消息,如果没有得到答复,则假设选项卡中没有内容脚本并插入内容脚本.
在弹出/后台脚本中:
chrome.tabs.executeScript(tabId, {
file: 'contentscript.js',
}, function(results) {
if (chrome.runtime.lastError || !results || !results.length) {
return; // Permission error, tab closed, etc.
}
if (results[0] !== true) {
// Not already inserted before, do your thing, e.g. add your CSS:
chrome.tabs.insertCSS(tabId, { file: 'yourstylesheet.css' });
}
});
contentscript.js:
// Wrapping in a function to not leak/modify variables if the script
// was already inserted before.
(function() {
if (window.hasRun === true)
return true; // Will ultimately be passed back to executeScript
window.hasRun = true;
// rest of code ...
// No return value here, so the return value is "undefined" (without quotes).
})(); // <-- Invoke function. The return value is passed back to executeScript
注意,window.hasRun
明确地检查值是非常重要的(true
在上面的例子中),否则它可以是具有id="hasRun"
属性的DOM元素的自动创建的全局变量,请参阅是否有规范要求元素的id应该成为全局变量?