本文介绍了Firefox插件页面显示事件在工作人员能够接收消息之前触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个firefox插件,并跟踪每个页面的工作人员在一个数组中。除了管理这个数组所需要的一些奇特步法之外(这里描述,这里)一切工作正常。我遇到的一个问题是,当听取标签 pageshow 事件(或工人自己的 pageshow 事件事情),这个回调似乎在工人实际准备好之前就开始了。当在回调中检索页面的相应工作人员并使用它来尝试向内容脚本发送消息时,我收到错误该页面当前被隐藏,并且不能再使用,直到其可见再一次。通常情况下,我只是使用一个setTimeout,咬牙切齿,但这不适用于附加组件。什么是合适的解决方法?这个插件主要部分的代码如下:
$ b $ pre $ var $ {ToggleButton} = require('sdk / ui /按钮/切换');
var panels = require('sdk / panel');
var tabs = require('sdk / tabs');
var self = require('sdk / self');
var pageMods = require('sdk / page-mod');
var ss = require('sdk / simple-storage');
var workers = [];

ss.storage.isPluginActive = ss.storage.isPluginActive ||假;

var button = ToggleButton({
id:'tomorrowww',
label:'Tomorowww',
icon:{
'16':' ./icon-16.png',
'32':'./icon-32.png',
'64':'./icon-64.png'
},
onChange:handleButtonChange
});

var panel = panels.Panel({
contentURL:self.data.url('panel.html'),
contentScriptFile:self.data.url('panel- script.js'),
onHide:handlePanelHide,
width:342,
height:270
});

panel.port.on('panel-ready',handlePanelReady);
panel.port.on('plugin-toggled',handlePluginToggled);
panel.port.on('link-clicked',handleLinkClicked);
$ b pageMods.PageMod({
include:['*'],
contentScriptFile:[self.data.url('CancerDOMManager.js'),self.data.url ('content-script.js')],
contentStyleFile:self.data.url('content-style.css'),
onAttach:function(worker){
addWorker );
sendActiveState(ss.storage.isPluginActive);
}
});
$ b $ //在标签之间移动
tabs.on('activate',function(){
sendActiveState();
});

//这实际上是在worker的pageshow事件之前触发的,所以没有用,因为workers数组不会同步
//tabs.on('pageshow',function(){
// sendActiveState();
//});
$ b $ function addWorker(worker){
if(workers.indexOf(worker)> -1){
return;
}

worker.on('detach',handleWorkerDetach);
worker.on('pageshow',handleWorkerShown);
worker.on('pagehide',handleWorkerHidden);
workers.push(worker);


函数handleWorkerDetach(){
removeWorker(this,true);


函数handleWorkerShown(){
addWorker(this);

//返回/转发页面历史记录
//尝试在这里发送状态会触发页面隐藏错误
sendActiveState();


函数handleWorkerHidden(){
removeWorker(this);


函数removeWorker(worker,removeEvents){
var index = workers.indexOf(worker);

removeEvents = removeEvents ||假;

if(index> -1){
if(removeEvents){
worker.removeListener('detach',handleWorkerDetach);
worker.removeListener('pageshow',handleWorkerShown);
worker.removeListener('pagehide',handleWorkerHidden);
}

workers.splice(index,1);



函数getWorkersForCurrentTab(){
var i;
var tabWorkers = [];

i = workers.length;

while(-i> -1){
if(workers [i] .tab.id === tabs.activeTab.id){
tabWorkers.push (工人[I]);
}
}

return tabWorkers;
}

函数handlePanelReady(){
setActive(ss.storage.isPluginActive);
}

函数setActive(bool){
ss.storage.isPluginActive = bool;
panel.port.emit('active-changed',bool);
sendActiveState();


函数sendActiveState(){
var tabWorkers = getWorkersForCurrentTab();
var i = tabWorkers.length; ($ i $ gt; -1){
tabWorkers [i] .port.emit('toggle-plugin',ss.storage.isPluginActive);





函数handleButtonChange(state){
if(state.checked){
panel.show({
position:按钮
});


$ b $函数handlePanelHide(){
button.state('window',{checked:false});


函数handleLinkClicked(url){
if(panel.isShowing){
panel.hide();
}

tabs.open(url);


函数handlePluginToggled(bool){
if(panel.isShowing){
panel.hide();
}

setActive(bool);


解决方案

问题。我想我现在通过将监听器放在 content 脚本中而不是 addon 脚本中来工作。我在窗口监听事件,然后从我的内容脚本发送消息到我的插件脚本,然后我的插件脚本将消息发送回内容脚本,并使用插件脚本所需的信息。



在我的代码中,我正在更新内容脚本中的首选项,以确保该选项卡在更改时始终具有最新的设置,只有插件脚本可以侦听偏好改变事件。

这个特定的代码片段会监听页面是否从历史记录导航(即后退或前进按钮),通知插件脚本,插件脚本将获得最新的首选项,然后将它们发送回监听内容脚本的端口。

内容脚本:



  window.onpageshow = function(){
console.log(onpageshow event fired(content script));
self.port.emit(triggerPrefChange,'');
};



插件脚本(例如,main.js:



  worker.port.on(triggerPrefChange,function(){
console.log(接收到addon脚本中的triggerPrefChange请求);
worker.port.emit(setPrefs,prefSet.prefs);
});

由于事件是从DOM事件中触发的,所以必须显示页面。我不确定是否在 addon 脚本中监听pageshow事件正在做我们想象的事情。


I'm writing a firefox plugin and keeping track of each page's workers in an array. Apart from a bit of fancy footwork required to manage this array (as described here https://bugzilla.mozilla.org/show_bug.cgi?id=686035 and here Addon SDK - context-menu and page-mod workers) everything is working properly. One issue I'm having is that when listening to the tabs pageshow event (or the worker's own pageshow event for that matter), the callback seems to fire before the worker is actually ready. When retrieving the page's corresponding worker in the callback and using it to try to send a message to the content script, I'm receiving the error The page is currently hidden and can no longer be used until it is visible again. Normally, I'd just use a setTimeout and grit my teeth, but this isn't available for add-ons. What's a suitable workaround? The code for the main part of the add-on is below:

var { ToggleButton } = require('sdk/ui/button/toggle');
var panels = require('sdk/panel');
var tabs = require('sdk/tabs');
var self = require('sdk/self');
var pageMods = require('sdk/page-mod');
var ss = require('sdk/simple-storage');
var workers = [];

ss.storage.isPluginActive = ss.storage.isPluginActive || false;

var button = ToggleButton({
    id: 'tomorrowww',
    label: 'Tomorowww',
    icon: {
        '16': './icon-16.png',
        '32': './icon-32.png',
        '64': './icon-64.png'
    },
    onChange: handleButtonChange
});

var panel = panels.Panel({
    contentURL: self.data.url('panel.html'),
    contentScriptFile: self.data.url('panel-script.js'),
    onHide: handlePanelHide,
    width: 342,
    height: 270
});

panel.port.on('panel-ready', handlePanelReady);
panel.port.on('plugin-toggled', handlePluginToggled);
panel.port.on('link-clicked', handleLinkClicked);

pageMods.PageMod({
    include: ['*'],
    contentScriptFile: [self.data.url('CancerDOMManager.js'), self.data.url('content-script.js')],
    contentStyleFile: self.data.url('content-style.css'),
    onAttach: function (worker) {
        addWorker(worker);
        sendActiveState(ss.storage.isPluginActive);
    }
});

// move between tabs
tabs.on('activate', function () {
    sendActiveState();
});

// this actually fires before the worker's pageshow event so isn't useful as the workers array will be out of sync
//tabs.on('pageshow', function () {
//    sendActiveState();
//});

function addWorker (worker) {
    if(workers.indexOf(worker) > -1) {
        return;
    }

    worker.on('detach', handleWorkerDetach);
    worker.on('pageshow', handleWorkerShown);
    worker.on('pagehide', handleWorkerHidden);
    workers.push(worker);
}

function handleWorkerDetach () {
    removeWorker(this, true);
}

function handleWorkerShown () {
    addWorker(this);

    // back / forward page history
    // trying to send the state here will trigger the page hidden error
    sendActiveState();
}

function handleWorkerHidden () {
    removeWorker(this);
}

function removeWorker (worker, removeEvents) {
    var index = workers.indexOf(worker);

    removeEvents = removeEvents || false;

    if(index > -1) {
        if(removeEvents) {
            worker.removeListener('detach', handleWorkerDetach);
            worker.removeListener('pageshow', handleWorkerShown);
            worker.removeListener('pagehide', handleWorkerHidden);
        }

        workers.splice(index, 1);
    }
}

function getWorkersForCurrentTab () {
    var i;
    var tabWorkers = [];

    i = workers.length;

    while(--i > -1) {
        if(workers[i].tab.id === tabs.activeTab.id) {
            tabWorkers.push(workers[i]);
        }
    }

    return tabWorkers;
}

function handlePanelReady () {
    setActive(ss.storage.isPluginActive);
}

function setActive (bool) {
    ss.storage.isPluginActive = bool;
    panel.port.emit('active-changed', bool);
    sendActiveState();
}

function sendActiveState () {
    var tabWorkers = getWorkersForCurrentTab();
    var i = tabWorkers.length;

    while(--i > -1) {
        tabWorkers[i].port.emit('toggle-plugin', ss.storage.isPluginActive);
    }
}

function handleButtonChange (state) {
    if(state.checked) {
        panel.show({
            position: button
        });
    }
}

function handlePanelHide () {
    button.state('window', {checked: false});
}

function handleLinkClicked (url) {
    if(panel.isShowing) {
        panel.hide();
    }

    tabs.open(url);
}

function handlePluginToggled (bool) {
    if(panel.isShowing) {
        panel.hide();
    }

    setActive(bool);
}
解决方案

I was dealing with a similar problem. I think I have it working the way I want now by putting the listener in the content script instead of the addon script. I listen for the event on the window, I then emit a message from my content script to my addon script, my addon script then sends a message back to the content script with the information needed from the addon script.

In my code, I am working on update the preferences in the content script to ensure that the tab always has the most up to date settings when they are changed, only the addon script can listen to the prefs change event.

This particular snippet will listen for when the page is navigated to from history (i.e., back or forward button), will inform the addon script, the addon script will get the most up to date preferences, and then send them back to a port listening in the content script.

Content script:

window.onpageshow = function(){
    console.log("onpageshow event fired (content script)");
    self.port.emit("triggerPrefChange", '');    
};

Addon Script (e.g., main.js:

worker.port.on("triggerPrefChange", function() {
      console.log("Received request to triggerPrefChange in the addon script");
      worker.port.emit("setPrefs", prefSet.prefs);
  });

Since the event is being fired from the DOM event, the page must be shown. I am not sure if listening to the pageshow event in the addon script is doing what we think.

这篇关于Firefox插件页面显示事件在工作人员能够接收消息之前触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 09:52