每次单击扩展图标时,调用chrome.tabs.executeScript
是否足够安全?换句话说,这是幂等的吗?
- 是的,除非您的内容脚本修改了页面的DOM并且重新加载了扩展程序(通过设置页面重新加载,更新等)。在这种情况下,旧的内容脚本将不再在扩展程序的上下文中运行,因此无法使用扩展API,也不能直接与您的扩展通信。
chrome.tabs.insertCSS
是否有类似的方法?
- 没有
chrome.tabs.insertCSS
的包含保护。但是重新插入相同的样式表不会改变页面的外观,因为所有规则具有相同的CSS特异性,并且在这种情况下,最后一个样式表优先。但是,如果样式表与您的扩展紧密耦合,则可以使用executeScript注入脚本,检查是否第一次注入,如果是,则插入样式表(请参见下面的示例)。
有更好的后台脚本检查内容脚本注入状态的方法吗,以便我可以防止用户每次单击图标时都调用chrome.tabs.executeScript
?
- 您可以向标签发送消息(
chrome.tabs.sendMessage
),如果没有收到回复,则假定该标签中没有内容脚本并插入内容脚本。
第2个问题的代码示例
在您的弹出窗口/后台脚本中:
chrome.tabs.executeScript(tabId, {
file: 'contentscript.js',
}, function(results) {
if (chrome.runtime.lastError || !results || !results.length) {
return;
}
if (results[0] !== true) {
chrome.tabs.insertCSS(tabId, { file: 'yourstylesheet.css' });
}
});
使用 contentScript.js
有两种解决方案:
- 直接使用 windows:不建议,因为每个人都可以更改那些变量,而且 是否有规范要求元素的 ID 应该成为全局变量?
- 使用 Chrome.storage API:您可以与其他窗口共享内容脚本的状态(缺点是您需要在
Manifest.json
上请求权限,但这是可以接受的,因为这是正确的方法。
选项1:contentscript.js:
(function() {
if (window.hasRun === true)
return true;
window.hasRun = true;
})();
注意,重要的是要明确检查window.hasRun
的值(在上面的示例中为true
),否则它可能会成为具有id =“hasRun”
属性的DOM元素的自动创建的全局变量,请参见是否有规范使元素的ID应该成为全局变量?
选项2:contentscript.js(使用chrome.storage.sync
,也可以使用chrome.storage.local
)
(chrome.storage.sync.get(['hasRun'], (hasRun)=>{
const updatedHasRun = checkHasRun(hasRun);
chrome.storage.sync.set({'hasRun': updatedHasRun});
))()
function checkHasRun(hasRun) {
if (hasRun === true)
return true;
hasRun = true;
};
window.hasRun ? true : (window.hasRun=true), (function(){ ... browserify output here that does not return true ... })();
(还有数十种其他变体,您只需要更改最后一个表达式的值即可)。 - Rob Wchrome.tabs.executeScript
获得了空返回值。这似乎与主题无关,我已经在http://stackoverflow.com/questions/34540906上发布了一个新的问题帖子。 - KF Lin