- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试从后台页面向内容脚本发送消息,然后从该内容脚本向注入(inject)脚本发送消息。我试过这个,但没有用。
这是我的代码的样子。
list .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"}));
});
注入(inject).js
document.addEventListener('Buffer2Remote', function(e){
alert(e.todo);
});
消息发送从第一部分开始不起作用,background -> content_script。我的代码有什么问题吗?
最佳答案
由于内容脚本的注入(inject)方式,您的脚本无法正常工作。
当您(重新)加载您的扩展程序时,与某些人的预期相反,Chrome 不会将内容脚本注入(inject)现有标签页以匹配 list 中的模式。只有在加载扩展后,任何导航才会检查匹配的 URL 并注入(inject)代码。
所以,时间轴:
chrome://extensions/
页面,无论如何你不能在那里注入(inject))1 - 如果您重新加载您的扩展,也会发生这种情况。如果注入(inject)了内容脚本,它会继续处理其事件/不会被卸载,但无法再与扩展通信。 (详情见文末附录)
解决方案 1:您可以先询问要向其发送消息的选项卡是否准备就绪,然后在保持沉默后以编程方式注入(inject)脚本。考虑:
// 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:始终注入(inject)脚本,但确保它只执行一次。
// 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:只是在初始化时不加选择地注入(inject)您的内容脚本。只有在两次运行相同的内容脚本或在页面完全加载后运行它是安全的情况下,才可以安全地执行此操作。
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; }
/* ... */
});
关于javascript - 将消息从后台脚本发送到内容脚本,然后再发送到注入(inject)脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23895377/
我有本地更改和远程更改。 有人告诉我必须先推,再 pull 。这背后有什么原因吗? 最佳答案 那个人错了:正确的模型是pull-before-you-push,而不是相反。 当您pull时,git 将
我正在使用最新版本的 Flat UI Pro 1.3.2 ( http://designmodo.com/flat/ ),jQuery 插件 flatui-radiocheck v0.1.0 和 iO
我是一名优秀的程序员,十分优秀!