Javascript 从firefox插件SDK中的内容脚本回调
我正在使用Firefox插件sdk开发一个小扩展,它必须改变页面中DOM元素的内容。我正在使用Javascript 从firefox插件SDK中的内容脚本回调,javascript,firefox,firefox-addon,firefox-addon-sdk,Javascript,Firefox,Firefox Addon,Firefox Addon Sdk,我正在使用Firefox插件sdk开发一个小扩展,它必须改变页面中DOM元素的内容。我正在使用PageMod添加内容脚本并注册一些事件,其中一些事件我希望通过回调函数传递给它们,如下所示: main.js pageMod.PageMod({ include: "*", contentScriptWhen: 'ready', contentScriptFile: [self.data.url("my_content_script.js")], onAttach: f
PageMod
添加内容脚本并注册一些事件,其中一些事件我希望通过回调函数传递给它们,如下所示:
main.js
pageMod.PageMod({
include: "*",
contentScriptWhen: 'ready',
contentScriptFile: [self.data.url("my_content_script.js")],
onAttach: function(worker) {
worker.port.on("processElement", function(elementSrc, callback) {
doSomeProcessingViaJsctypes();
callback("http://someUrl/image.png");
});
}
});
var elements = document.getElementsByTagName("img");
var elementsLength = elements.length;
for (var i = 0; i < elementsLength; i++)
{
(function(obj) {
obj.setAttribute("data-processed", "true");
self.port.emit("processElement", obj.src, function(newSrc) {
console.log("replaced " + obj.src);
obj.src = newSrc;
});
})(elements[i]);
}
my\u content\u script.js
pageMod.PageMod({
include: "*",
contentScriptWhen: 'ready',
contentScriptFile: [self.data.url("my_content_script.js")],
onAttach: function(worker) {
worker.port.on("processElement", function(elementSrc, callback) {
doSomeProcessingViaJsctypes();
callback("http://someUrl/image.png");
});
}
});
var elements = document.getElementsByTagName("img");
var elementsLength = elements.length;
for (var i = 0; i < elementsLength; i++)
{
(function(obj) {
obj.setAttribute("data-processed", "true");
self.port.emit("processElement", obj.src, function(newSrc) {
console.log("replaced " + obj.src);
obj.src = newSrc;
});
})(elements[i]);
}
var elements=document.getElementsByTagName(“img”);
var elementsLength=elements.length;
对于(变量i=0;i
错误
TypeError: callback is not a function
Stack trace:
.onAttach/<@resource://gre/modules/XPIProvider.jsm -> file:///c:/users/sebast~1/appdata/local/temp/tmpjprtpo.mozrunner/extensions/jid1-gWyqTW27PXeXmA@jetpack/bootstrap.js -> resource://gre/modules/commonjs/toolkit/loader.js -> resource://jid1-gwyqtw27pxexma-at-jetpack/testextension/lib/main.js:53
TypeError:回调不是函数
堆栈跟踪:
.Onatach/file:///c:/users/sebast~1/appdata/local/temp/tmpjprtpo.mozrunner/extensions/jid1-gWyqTW27PXeXmA@jetpack/bootstrap.js->resource://gre/modules/commonjs/toolkit/loader.js -> resource://jid1-gwyqtw27pxexma-at-jetpack/testextension/lib/main.js:53
我似乎在网上找不到关于这件事的任何信息。我需要这种方法,因为处理需要一点时间,并且依赖于.dll文件,所以我无法从内容脚本调用它
如果我要处理元素并在调用之后调用worker.port.emit()
,我必须再次遍历整个树以识别元素并更改其src
属性。这将花费很长时间,并且会为文档中的每个img
添加额外的循环
我考虑过生成一个唯一的类名并将其附加到元素的类中,然后调用getElementsByClassName()
。我没有对此进行测试,但在我看来,这将花费与我上面描述的过程相同的时间
如有任何建议,将不胜感激
编辑:我发现了一个不同的问题。建议使用windowutils
获取activeBrowserWindow
,然后对其内容进行迭代
他还提到
这些低级API不能保证是稳定的,window utils模块甚至没有完整的文档记录
从那以后有什么变化吗?我想知道是否可以使用选项卡获得相同的content
属性,以及是否可以识别工作人员从哪个选项卡发送self.port.emit()
当在内容脚本和模块(main.js
)之间使用消息传递时,只能传递JSON可序列化的数据
传递应该可以,因为这是一个字符串,因此JSON是可序列化的。
您的代码由于您试图传递的回调函数而中断,因为函数
不可JSON序列化(与整个DOM节点不可JSON序列化相同)。
另外,.emit
和.on
仅使用第一个参数作为消息负载
在完成处理后,您必须向内容脚本发出另一条消息,而不是回调。由于不能传递DOM元素,所以需要跟踪DOM元素属于哪个消息
好吧,举个例子,我会怎么做。
第一个main.js
:
const self = require("sdk/self");
const {PageMod} = require("sdk/page-mod");
function processImage(src) {
return src + " dummy";
}
PageMod({
include: "*",
contentScriptWhen: 'ready',
contentScriptFile: [self.data.url("content.js")],
onAttach: function(worker) {
worker.port.on("processImage", function(data) {
worker.port.emit("processedImage", {
job: data.job,
newSrc: processImage(data.src)
});
});
}
});
在我的设计中,每个processImage
消息都有一个与之相关联的job
(请参阅内容脚本),它main.js
认为是不透明的,只会逐字逐句地发回响应
现在,data/content.js
,又名。我的内容脚本:
var jobs = new Map();
var jobCounter = 0;
self.port.on("processedImage", function(data) {
var img = jobs.get(data.job);
jobs.delete(data.job);
var newSrc = data.newSrc;
console.log("supposed replace", img.src, "with", newSrc);
});
for (var i of document.querySelectorAll("img")) {
var job = jobCounter++; // new job number
jobs.set(job, i);
self.port.emit("processImage", {
job: job,
src: i.src
});
}
因此,本质上,对于每个映像,我们将创建一个作业编号(可以是uuid或其他任何东西,但是增加一个计数器对于我们的用例来说已经足够了),并将与该作业编号关联的DOM映像放入一个映射中以跟踪它。
之后,只需将消息发布到main.js
processedImage
处理程序将接收回作业编号和新源,使用作业编号和jobs
map返回DOM元素,再次将其从映射中删除(我们不想泄漏它的内容),并执行任何需要的处理;在本例中,只需记录内容。这是一个非常好且优雅的解决方案。非常感谢你。我已经对它进行了测试,即使使用jsctypes
后面的处理,它的运行速度也相当快。