Javascript 将消息从后台脚本发送到内容脚本,然后再发送到注入脚本
我试图将消息从后台页面发送到内容脚本,然后将消息从该内容脚本发送到注入脚本。我试过这个,但不起作用 下面是我的代码 manifest.jsonJavascript 将消息从后台脚本发送到内容脚本,然后再发送到注入脚本,javascript,google-chrome-extension,Javascript,Google Chrome Extension,我试图将消息从后台页面发送到内容脚本,然后将消息从该内容脚本发送到注入脚本。我试过这个,但不起作用 下面是我的代码 manifest.json { "manifest_version": 2, "name": "NAME", "description": ":D", "version": "0.0", "permissions": [ "tabs","<all_urls>" ], "content_scripts": [ {
{
"manifest_version": 2,
"name": "NAME",
"description": ":D",
"version": "0.0",
"permissions": [
"tabs","<all_urls>"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content_script.js"]
}
],
"web_accessible_resources": [
"injected.js"
],
"background":{
"scripts":["background.js"]
}
}
content\u script.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response){});
});
var s = document.createElement('script');
s.src = chrome.extension.getURL('injected.js');
s.onload = function(){
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
document.dispatchEvent(new CustomEvent('Buffer2Remote', {todo: "LOL"}));
});
document.addEventListener('Buffer2Remote', function(e){
alert(e.todo);
});
injected.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response){});
});
var s = document.createElement('script');
s.src = chrome.extension.getURL('injected.js');
s.onload = function(){
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
document.dispatchEvent(new CustomEvent('Buffer2Remote', {todo: "LOL"}));
});
document.addEventListener('Buffer2Remote', function(e){
alert(e.todo);
});
从第一部分“背景->内容”脚本发送消息不起作用。
我的代码有什么问题吗?由于内容脚本的注入方式,您的脚本无法工作 问题 当您(重新)加载扩展时,与一些人期望的相反,Chrome不会将内容脚本注入到与清单中的模式匹配的现有选项卡中。只有在加载扩展后,任何导航都将检查URL是否匹配,并将插入代码 因此,时间表:
chrome://extensions/
页面,但无论如何都不能在那里注入)// Background
function ensureSendMessage(tabId, message, callback){
chrome.tabs.sendMessage(tabId, {ping: true}, function(response){
if(response && response.pong) { // Content script ready
chrome.tabs.sendMessage(tabId, message, callback);
} else { // No listener on the other end
chrome.tabs.executeScript(tabId, {file: "content_script.js"}, function(){
if(chrome.runtime.lastError) {
console.error(chrome.runtime.lastError);
throw Error("Unable to inject script into tab " + tabId);
}
// OK, now it's injected and ready
chrome.tabs.sendMessage(tabId, message, callback);
});
}
});
}
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
ensureSendMessage(tabs[0].id, {greeting: "hello"});
});
及
解决方案2:始终注入脚本,但确保它只执行一次。
// Background
function ensureSendMessage(tabId, message, callback){
chrome.tabs.executeScript(tabId, {file: "content_script.js"}, function(){
if(chrome.runtime.lastError) {
console.error(chrome.runtime.lastError);
throw Error("Unable to inject script into tab " + tabId);
}
// OK, now it's injected and ready
chrome.tabs.sendMessage(tabId, message, callback);
});
}
及
这比较简单,但在扩展重新加载时会比较复杂。重新加载扩展后,旧脚本仍然存在,但它不再是“您的”上下文-因此注入的将是未定义的。小心可能执行脚本两次的副作用
解决方案3:只需在初始化时不加区分地注入内容脚本即可。只有在安全地运行同一内容脚本两次,或者在页面完全加载后运行它时,才可以安全地执行此操作
chrome.tabs.query({}, function(tabs) {
for(var i in tabs) {
// Filter by url if needed; that would require "tabs" permission
// Note that injection will simply fail for tabs that you don't have permissions for
chrome.tabs.executeScript(tabs[i].id, {file: "content_script.js"}, function() {
// Now you can use normal messaging
});
}
});
我还怀疑您希望它在某些操作上运行,而不是在扩展负载上运行。例如,您可以使用一个函数,并将代码包装在chrome.browserAction.onClicked
侦听器中
关于孤立内容脚本的增编
当一个扩展被重新加载时,人们会期望Chrome清理所有的内容脚本。但显然情况并非如此;未禁用内容脚本的侦听器。但是,任何带有父扩展名的消息传递都将失败。这可能会被视为一个bug,并可能在某个时候得到修复。我要称这个州为“孤儿”
在以下两种情况下,这都不是问题:
内容脚本没有页面上事件的侦听器(例如,仅执行一次,或仅侦听来自后台的消息)
内容脚本对页面没有任何作用,只向背景发送有关事件的消息李>
然而,如果不是这样的话,那么您就有一个问题:内容脚本可能正在做一些事情,但失败或干扰了自身的另一个非孤立实例
解决办法是:
跟踪页面可以触发的所有事件侦听器
在对这些事件采取行动之前,向后台发送“心跳”消息。
3a。如果背景有反应,我们很好,应该执行这个动作。
3b。如果消息传递失败,我们就成了孤儿,应该停止;忽略事件并取消注册所有侦听器
代码、内容脚本:
function heartbeat(success, failure) {
chrome.runtime.sendMessage({heartbeat: true}, function(reply){
if(chrome.runtime.lastError){
failure();
} else {
success();
}
});
}
function handler() {
heartbeat(
function(){ // hearbeat success
/* Do stuff */
},
function(){ // hearbeat failure
someEvent.removeListener(handler);
console.log("Goodbye, cruel world!");
}
);
}
someEvent.addListener(handler);
背景脚本:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.heartbeat) { sendResponse(request); return; }
/* ... */
});
在mybackground.js中
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
if (tab.url !== undefined && info.status == "complete") {
chrome.tabs.query({active: true, currentWindow: true, status: "complete"}, function (tabs) {
console.log(tabs);
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function (response) {
console.log(response.farewell);
});
});
}
});
我的manifest.json
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": [
"content_script.js"
],
"run_at": "document_end"
}
我的“content_sciprt.js”在“background.js”之后工作。所以我无法收到回复
但是在我加上
info.status==“完成”
,状态:“完成”
“run\u at”:“document\u end”
在my manifest.json中
它工作正常您的清单中有一个输入错误,content\u脚本中有一个额外的逗号
@Xan我修复了它,但仍然不起作用。实际上,现在我想我遇到了您提到的关于杀死content\u脚本上的侦听器的问题。你能解释一下吗?Chrome不允许通过executeScript“无法访问Chrome://URL”注入内容脚本。有没有其他方法注入它们?@parats不在chrome://
页面中,不。你不能触摸这些。哦,所以在其他页面中,应该没有错误。对吗?如果是孤儿院,您可以简单地检查chrome.runtime.id
而不是检查心跳,它将是未定义的。if(chrome.runtime.id==未定义)返回;