我尝试将消息从后台页面发送到内容脚本,然后将该内容脚本中的消息发送到注入的脚本。我试过这个,但它没有用。
这是我的代码的样子。
的manifest.json
{
"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"]
}
}
background.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response){});
});
content_script.js
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"}));
});
injected.js
document.addEventListener('Buffer2Remote', function(e){
alert(e.todo);
});
发送的消息不是第一部分,背景 - &gt; content_script。 我的代码有什么问题吗?
答案 0 :(得分:45)
由于内容脚本的注入方式,您的脚本无效。
当您(重新)加载扩展程序时,与某些人的预期相反,Chrome 不会将内容脚本注入到与清单中的模式匹配的现有标签中。只有在加载扩展后,任何导航都会检查URL是否匹配,并将注入代码。
所以,时间表:
chrome://extensions/
页面,无论如何都不能注入)1 - 如果您重新加载扩展程序,也会发生这种情况。如果注入了内容脚本,它将继续处理其事件/不会被卸载,但无法再与扩展进行通信。 (详情见最后的附录)
解决方案1:您可以先向选项卡询问您是否已准备好,并在静默时以编程方式注入脚本。考虑:
// 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"});
});
和
// Content script
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.ping) { sendResponse({pong: true}); return; }
/* Content script action */
});
解决方案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);
});
}
和
// Content script
var injected;
if(!injected){
injected = true;
/* your toplevel code */
}
这更简单,但在扩展重新加载方面存在复杂性。重新加载扩展后,旧脚本仍然存在 1 ,但它不再是“您的”上下文 - 因此injected
将是未定义的。请注意可能两次执行脚本的副作用。
解决方案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
});
}
});
我还怀疑你希望它在某些动作上运行,而不是在扩展加载上运行。例如,您可以使用Browser Action并将代码包装在chrome.browserAction.onClicked
侦听器中。
当重新加载扩展程序时,人们会希望Chrome清理所有内容脚本。但显然事实并非如此;内容脚本的侦听器未被禁用。但是,任何具有父扩展的消息都将失败。 这应该被视为一个错误,并且可能在某些时候被修复。我将把这个状态称为“孤儿”
在以下两种情况中都不是问题:
然而,如果情况并非如此,那么你就会遇到一个问题:内容脚本可能正在做某事但却失败或干扰了另一个非孤立的实例。
解决方法是:
代码,内容脚本:
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; }
/* ... */
});
答案 1 :(得分:-1)
在我的background.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"
}
我的&#34; content_sciprt.js&#34;在&#34; background.js&#34;之后工作。所以我无法收到回复。
但是在我添加
之后info.status=="complete"
,status: "complete"
"run_at": "document_end"
醇>
工作正常