PageMod多次将工作人员附加到相同的URL [英] PageMod attaching worker to same URL multiple times

查看:64
本文介绍了PageMod多次将工作人员附加到相同的URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

找到了一个非常干净的解决方案,这个问题真的使整个问题变得毫无意义,而且我确信当我问这个问题...我太无知了太多了。



使用 attachTo:'top' PageMod中构造函数只将脚本附加到顶层文档,而不是附加到 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 +']:+
我的工作人员向我打招呼!);,
contentScriptWhen:end,
attachTo:'top',//< - 将此属性添加到只附加到顶级文档
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 +']:+
我的工人向我打招呼!);,
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 /]:我的工人向我打招呼!

这意味着同一页面上有多个工作者。 我不知道为什么会发生这种情况,我当然不希望这样,因为我打算稍后使用 _workers 数组来与附加的脚本进行通信。

编辑



感谢@Noitidart,现在已经证实,在多个工作人员中,只有一个是实际的页面,其他的是iframe,这就是为什么每个工作人员的内容脚本可用的DOM内容是不同的。



但问题仍然存在。如何确保工作人员(因此,内容脚本)不附加到iframe?



我可以确保未附加到 iframe 的工作人员被推送到 _workers ,但有没有办法将内容脚本附加到工作人员,一旦我确定它是正确的?我不希望相当大的内容脚本被多次附加。



编辑2

再一次,感谢@Noitidart,我想我有一些解决方法:如果检测到工作者被附加到 iframe ,则销毁。

更好的解决方案是只将主内容脚本附加到正确的工作人员,但目前我一直无法找到一种方法将内容脚本附加到正确的worker( worker.contentScriptFile = data.url(file.js)似乎不起作用)。



<所以,目前的破解:

verify.js

<$ p $ 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:函数(worker){
worker.on(detach,function(){
var ind = _workers.indexOf(this);
if(ind!== -1){
_workers.splice(ind,1);
}
});

worker.port.on(hi,function(){
//不是iframe,保留这个
//如果有方法,现在把'my_main_script.js'
//附加到这个worker上,而不是之前

_workers.push(worker);

//发送'ack'告诉my_main_script.js
//我们很好去
worker.port.emit( 'ack');
});

worker.port.on(iframe,function( ){
// iframe,摆脱它。
worker.destroy();
});
}
});

我应该注意到在 contentScriptFile 无关紧要,两个脚本都是为每个附件加载的。所以没有人希望 verify.js 在加载 my_main_script.js 之前销毁工作者。

同样,这个解决方案不完整。如果我没有足够强调这一点,我真的希望有一种方法可以将 my_main_script.js 附加到正确的worker上,而不是让所有worker加载。如果有这样的一个方法,请评论/回答。

解决方案

在contentScript或任何正在运行的网站(我不知道很多有关SDK),检查 if(window.frameElement == true)如果它的真正比它的一个框架,那么你想取消附加。



编辑:
也许window.frameElement不会在框架内工作。 if(window.top!= window)
那么它是一个框架

CLEAN SOLUTION FOUND

I found a very clean solution which really renders this whole question pointless, and I am certain it existed when I asked this question... I was much to ignorant too look for it.

Using attachTo: 'top' in the PageMod constructor only attaches the script to the top-level documents and not to any iframes.

So, if you find that PageMod is attaching multiple times for your add-on, it is probably due to it being attached to iframes, along with the top level tab document. Add attachTo: 'top' as a property for the object passed to the PageMod constructor, and you wouldn't need to worry about iframes.

For the question below, the solution would be

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");
    }
});

Of course, without @Noitidart's help, I never would have pinpointed the reason to be iframes.

OLD QUESTION

I'm trying to write an add-on for Firefox which modifies the pages of a particular website. I thought PageMod was the perfect option for that, but I've run into some problems. The workers seem to be attaching to the same URL multiple times (4 to 2), and I haven't got a clue why this would be happening.

I tried the following code in the add-on's 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");
    }
});

On running this code and opening https://www.websitename.net in a single, solitary tab, the console had 2 to 4 instances of

[https://www.websitename.net/]: My worker said hello to me!

Which means that the same page has multiple workers attached to it. I don't know why this is happening, I certainly don't want it to because I intend to later use the _workers array to communicate with the attached scripts.

EDIT:

Thanks to @Noitidart, I've now confirmed that of the multiple workers, only one is the actual page and the others are iframes, which is why the DOM content available to the content scripts for each worker was different.

The question still stands, though. How to ensure that the workers (and thus, the content scripts) are not attached to the iframes?

I could ensure that the worker that isn't attached to an iframe is the one pushed to _workers, but is there a way to attach a content script to a worker once I've ensured it is the correct one? I don't want the rather large content script to be attached multiple times.

EDIT 2:

Again, thanks to @Noitidart, I think I have somewhat of a solution: destroy if worker is detected to be attached to an iframe.

A better solution would be to only attach the main content script to the correct worker, but presently I have been unable to find a way to attach a content script to the correct worker (worker.contentScriptFile = data.url("file.js") doesn't seem to work).

So, the current 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();
        });
    }
});

I should note that the order in which the scrips appear in contentScriptFile doesn't matter, both scripts are loaded for each attachment. So no point hoping that verify.js destroys the worker before my_main_script.js is loaded.

And again, this solution is not complete. If I haven't emphasized enough on this point, I really hope there's a way to attach my_main_script.js to the correct worker, instead of having it load for all workers. Please comment/answer if there is such a way.

解决方案

In the contentScript or whatever is running in the web site (i dont know much about sdk), check if (window.frameElement == true) if its true than its a frame then you want to cancel the attach.

edit: maybe window.frameElement wont work from within the frame. if it doesnt work do this if (window.top != window) then its a frame

这篇关于PageMod多次将工作人员附加到相同的URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆