我试图写一个Chrome扩展,将有一个栏在某些网页的顶部。如果我的内容脚本是这样的:
$('body').prepend('<div id="topbar"><h1>test</h1></div>');
一切看起来都很好,但我最终想要的是这样的东西:
$('body').prepend('<div id="topbar"></div>');
$('#topbar').load('topbar.html');
其中topbar.html为:
<h1>test</h1>
当我把它改成这个的时候,网页就乱了。大部分内容都消失了,我只能看到一些广告。我甚至看不到"测试"标题。我已经检查以确保页面上没有其他"topbar"id。怎么了?
扩展文件夹内文件的URL格式如下:
chrome-extension://<ID>/topbar.html
你可以通过命令
得到这个路径。chrome.extension.getURL("topbar.html")
现在如果你尝试做:
$('#topbar').load(chrome.extension.getURL("topbar.html"));
由于跨域策略,它不会让你这样做。背景页没有这个限制,所以您需要在那里加载HTML并将结果传递给内容脚本:
content_script.js :
chrome.extension.sendRequest({cmd: "read_file"}, function(html){
$("#topbar").html(html);
});
background.html :
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if(request.cmd == "read_file") {
$.ajax({
url: chrome.extension.getURL("topbar.html"),
dataType: "html",
success: sendResponse
});
}
})
在现实世界中,您可能只会阅读一次topbar.html,然后重用它。
虽然上述解决方案确实有效,但需要注意的一点是,您需要从事件处理程序返回true,以便在$之后通信端口仍然可用。Ajax调用成功。
参见下面的更多信息。https://code.google.com/p/chromium/issues/detail?id=307034
纯js解决方案
在你的manifest.json
:
{
"manifest_version": 3,
# [...]
"web_accessible_resources": [{
"matches": ["<all_urls>"],
"resources": ["topbar.html"]
}]
}
在你的content.js
:
async function load_toolbar() {
let newElement = new DOMParser().parseFromString('<div id="toolbar"></div>', 'text/html').body.childNodes[0];
let toolbar_url = chrome.runtime.getURL("toolbar.html");
document.querySelector("body").appendChild(newElement);
document.getElementById("toolbar").innerHTML = await (await fetch(toolbar_url)).text();
}
load_toolbar();
仅供参考,现在在2020年,chrome.extension。onRequest已弃用,并且在加载扩展时导致错误。相反,应该使用chrome.runtime.sendMessage。对于content.js,代码现在应该是:
chrome.runtime.sendMessage({cmd: "read_file"}, function(html){
$("#topbar").html(html);
});
和background.js的代码现在是:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.cmd == "read_file") {
$.ajax({
url: chrome.extension.getURL("topbar.html"),
dataType: "html",
success: sendResponse
});
return true;
}
})
一定要注意ajax后的'return true',这绊倒了我