我正在编写一个扩展程序,它将调用内容脚本并完成一些工作。内容脚本的活动取决于首选项。我希望实时更新首选项,而不仅仅是选项卡加载。我已经设置了一个正确触发的监听器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。我仍然想知道如何使用这个原始代码完成同样的事情,以便理解一切如何协同工作。
答案 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
中实现的功能将被重新加载并使用用户设置的新首选项运行。