实时更新多个选项卡中的首选项worker.emit

时间:2014-08-16 03:37:24

标签: firefox-addon firefox-addon-sdk

我正在编写一个扩展程序,它将调用内容脚本并完成一些工作。内容脚本的活动取决于首选项。我希望实时更新首选项,而不仅仅是选项卡加载。我已经设置了一个正确触发的监听器require("sdk/simple-prefs").on("", onPrefChange);

var tabs = require("sdk/tabs");
var self = require("sdk/self");
var prefSet = require("sdk/simple-prefs");
var pageMod = require("sdk/page-mod");
var data    = self.data;

var workers = {};

prefSet.on("", onPrefChange);

function onPrefChange(prefName) {
    for each (var tab in tabs){     
        // the below code created a new worker and re-attached the script instead of reusing the worker
        // created in tabs.on('ready'...
        //changeWorker = tab.attach({
        //  contentScriptFile: self.data.url("my-script.js"),
        //});       
        //changeWorker.port.emit("setPrefs", prefSet.prefs);
        workers[tab.id].port.emit("setPrefs", prefSet.prefs);
    }
    console.log(workers);
}

tabs.on('ready', function(tab) {
    worker = workers[tab.id] = tab.attach({
        contentScriptFile: self.data.url("my-script.js"),
    });     
    worker.port.emit("setPrefs", prefSet.prefs);
});

tabs.on('close', function(tab) {
    delete workers[tab.id];
});

我开始使用this question中的一些代码,但我没有使用PageMod。我尝试用我的代码做类似的事情,但它不会从ready监听器中正确启动。在我的onPrefChange函数中,我最初重新附加了contentScriptFile,但这创建了一个新的附件和工作者。从this question开始,我发现我可以创建一个工作数组,然后再调用它。上面的代码按预期工作,但效率似乎不高。

我想知道是否有办法在onPrefChange侦听器内部设置ready,或者遍历选项卡列表并找到附加的工作人员;我无法弄清楚如何迭代选项卡并重用已经创建的工作程序(这将消除管理workers数组的需要)。另一种询问方式是给出一个标签,如何列出所有附加的工人?对首选项的更新应影响所有打开的选项卡,而不仅仅是最后创建的工作程序或当前选项卡,这是我尝试的其他一些方法的情况。


修改

如果在一个标签中我从http://www.example.com开始,然后导航到http://www.example.org并点击后退按钮,setPreferences将不会触发,我将收到错误:“该页面是目前已隐藏,在再次可见之前无法再使用。“它看起来像我附加工作者的方式,然后在迭代选项卡时调用iy是不正确的。我希望它继续当前可见的页面,但它只想在最后加载的页面上工作。也许在每次加载页面时,它会创建一个新的worker并替换数组中的现有值,而worker是否附加到页面而不是tab?

编辑2: 我一直在尝试使用PageMod来实现这一点。 可见的页面可能是另一个问题,as I discovered here。我仍然想知道如何使用这个原始代码完成同样的事情,以便理解一切如何协同工作。

1 个答案:

答案 0 :(得分:1)

我无法弄清楚如何找到标签中的所有工作人员,但为了解决我的问题,我能够遍历所有工作人员。如果您有单个工作人员,则可以查找选项卡。对于发送首选项,您实际上不需要知道选项卡。

这是我附加到首选项更改侦听器的函数:

prefSet.on("", onPrefChange = function(){

    for each (var thisTabWorker in tabWorkers){
        console.log("tab worker tab id= " + thisTabWorker.tab.id);
        console.log("tab worker url="  + thisTabWorker.url);
        thisTabWorker.port.emit("setPrefs", prefSet.prefs);
    }

});

我创建了worker并在main.js中附加了内容脚本:

var tabWorkers = [];

exports.main = function() {

    tabs.on('ready', function(tab) {
        tabWorker = tabWorkers[tab.id] = tab.attach({
        contentScriptFile: self.data.url("my-script.js")
        });
        workerTabId = tabWorker.tab.id;

        tabWorker.port.on("triggerPrefChange", function() {
          tabWorker.port.emit("setPrefs", prefSet.prefs);
        });

        tabWorker.on('detach', function () {
        delete tabWorkers[workerTabId];
        });

    }); 

}

triggerPrefChange是一条消息,可以从插件脚本发送,以便根据页面事件请求更改更新,这对于基本功能来说不是必需的。在这种情况下,如果您将其删除,则需要自行调用tabWorker.port.emit("setPrefs", prefSet.prefs);,以便最初发送首选项。

在我的内容代码(my-script.js

var someStringPreference = '';

self.port.on("setPrefs", function(prefs) {
    //assign a variable from the preferences array to 
    //a local varaible to be used in my.script.js
    someStringPreference = prefs["someStringPreference"].trim();
});

setPrefs中,您可能还想调用某个函数或触发事件,以便在您拥有这些新偏好时执行某些操作。

也在my-script.js

window.onpageshow = function(){
    self.port.emit("triggerPrefChange", '');    
};

我不会在附加工作人员时发出偏好,而是等到网页触发onpageshow。这也允许我在后退/前进导航中再次发送当前首选项 - 可能不需要所有情况。

到目前为止,这段代码似乎正在做我想要的而没有错误:每当更改首选项时,my-script.js中实现的功能将被重新加载并使用用户设置的新首选项运行。