【发布时间】:2014-03-13 14:45:18
【问题描述】:
找到干净的解决方案
我找到了一个非常干净的解决方案,它确实使整个问题变得毫无意义,当我问这个问题时,我确信它存在......我也太无知了。
在PageMod 构造函数中使用attachTo: 'top' 只会将脚本附加到顶级文档,而不是任何iframes。
因此,如果您发现 PageMod 为您的附加组件附加了多次,这可能是由于它与顶级选项卡文档一起附加到 iframes。添加attachTo: 'top' 作为传递给PageMod 构造函数的对象的属性,您无需担心iframes。
对于下面的问题,解决方案是
var _workers = [];
var pageMod = require("sdk/page-mod").PageMod({
include: /https?:\/\/www\.websitename\.net.*/,
contentScript: "self.port.on('hello', function() { " +
"console.log('['+document.location.href+']: " +
"My worker said hello to me!');",
contentScriptWhen: "end",
attachTo: 'top', //<-- add this property to only attach to top level document
onAttach: function(worker) {
_workers.push(worker);
worker.on("detach", function() {
var ind = _workers.indexOf(this);
if(ind !== -1) {
_workers.splice(ind, 1);
}
});
worker.port.emit("hello");
}
});
当然,如果没有@Noitidart 的帮助,我永远无法确定成为iframes 的原因。
老问题
我正在尝试为 Firefox 编写一个插件来修改特定网站的页面。我认为PageMod 是完美的选择,但我遇到了一些问题。工作人员似乎多次(4 到 2 次)附加到同一个 URL,我不知道为什么会发生这种情况。
我在插件的main.js中尝试了以下代码:
var _workers = [];
var pageMod = require("sdk/page-mod").PageMod({
include: /https?:\/\/www\.websitename\.net.*/,
contentScript: "self.port.on('hello', function() { " +
"console.log('['+document.location.href+']: " +
"My worker said hello to me!');",
contentScriptWhen: "end",
onAttach: function(worker) {
_workers.push(worker);
worker.on("detach", function() {
var ind = _workers.indexOf(this);
if(ind !== -1) {
_workers.splice(ind, 1);
}
});
worker.port.emit("hello");
}
});
在运行此代码并在一个单独的选项卡中打开 https://www.websitename.net 时,控制台有 2 到 4 个实例
[https://www.websitename.net/]: My worker said hello to me!
这意味着同一个页面有多个附加到它的工作人员。 我不知道为什么会这样,我当然不希望这样,因为我打算稍后使用 _workers 数组与附加的脚本进行通信。
编辑:
感谢@Noitidart,我现在已经确认在多个工作人员中,只有一个是实际页面,其他是 iframe,这就是每个工作人员的内容脚本可用的 DOM 内容不同的原因。
不过,问题仍然存在。如何确保工作人员(以及内容脚本)不附加到 iframe?
我可以确保未附加到 iframe 的工作人员是推送到 _workers 的工作人员,但是一旦我确保内容脚本是正确的,有没有办法将内容脚本附加到工作人员一?我不希望多次附加相当大的内容脚本。
编辑 2:
再次感谢@Noitidart,我想我有一些解决方案:如果检测到工人被附加到iframe,则销毁。
更好的解决方案是仅将主要内容脚本附加到正确的工作人员,但目前我无法找到将内容脚本附加到正确工作人员的方法(worker.contentScriptFile = data.url("file.js") 似乎不起作用) .
所以,当前的 hack:
verify.js:
if(window.top !== window) {
self.port.emit('iframe');
}
else {
self.port.emit('hi');
}
main.js:
var _workers = [];
var pageMod = require("sdk/page-mod").PageMod({
include: /https?:\/\/www\.websitename\.net.*/,
contentScriptFile: [data.url("verify.js"), data.url("my_main_script.js")],
contentScriptWhen: "end",
onAttach: function(worker) {
worker.on("detach", function() {
var ind = _workers.indexOf(this);
if(ind !== -1) {
_workers.splice(ind, 1);
}
});
worker.port.on("hi", function() {
//Not iframe, keep this one.
//If there is a way, attach 'my_main_script.js'
//to this worker now, and not before.
_workers.push(worker);
//Emit 'ack' to tell my_main_script.js
//that we're good to go.
worker.port.emit('ack');
});
worker.port.on("iframe", function() {
//iframe, get rid of it.
worker.destroy();
});
}
});
我应该注意,脚本出现在contentScriptFile 中的顺序无关紧要,两个脚本都会为每个附件加载。所以希望 verify.js 在 my_main_script.js 加载之前销毁工作人员是没有意义的。
同样,这个解决方案并不完整。如果我在这一点上没有足够强调,我真的希望有一种方法可以将 my_main_script.js 附加到正确的工作人员,而不是让所有工作人员都加载它。如果有这种方法,请评论/回答。
【问题讨论】:
-
您的文档中有 iframe 吗?他们也可能会依附于此。
-
@Noitidart 实际上,是的。并且文档中 iframe 的数量似乎与工人被附加的次数相对应。不错的收获!有没有办法阻止脚本附加到 iframe?
-
+1 分享解决方案谢谢
-
我无法告诉您我多么感谢您分享了解决方案。我差点被那个错误发疯。非常感谢,伙计!
标签: javascript firefox firefox-addon firefox-addon-sdk