简体   繁体   English

如何在firefox插件中只运行一个代码实例?

[英]How to run only one instance of code in a firefox addon?

I listen for a onload event on a main window, then for a DOMContentLoaded event on each browser/tab (I need run the code inside a browser at the most) and flag with controlExecuted that the code was run on a browser. 我在主窗口上监听onload事件,然后在每个浏览器/选项卡上监听DOMContentLoaded事件(我最多需要在浏览器中运行代码)并使用controlExecuted标记代码是在浏览器上运行的。

window.addEventListener("load", function(){
    try{
        var controlExecuted = 0;
        var appcontent = document.getElementById("appcontent"); // browser
        if (appcontent && controlExecuted == 0)
            appcontent.addEventListener("DOMContentLoaded", function docLoader(e){
                appcontent.removeEventListener("DOMContentLoaded", docLoader, false);
                alert('run code')
                controlExecuted = 1;
            }, true);
    }catch(e){
        // log!
    }
}, false);

This not works. 这不起作用。 The code run several times depending of the number of browsers/tabs. 代码运行多次,具体取决于浏览器/选项卡的数量。

So how to run only one instance of code in a firefox addon? 那么如何在firefox插件中只运行一个代码实例呢?

As you've noticed, your code runs each time a new browser window is opened. 正如您所注意到的,每次打开新的浏览器窗口时,您的代码都会运行。 What you might not have realized is that a script in one window is completely independent of the same script in another window. 您可能没有意识到的是,一个窗口中的脚本完全独立于另一个窗口中的相同脚本。 That is, a new set of objects is instantiated each time, which means that controlExecuted in one window is not the same object as controlExecuted in another window. 也就是说,新的一组对象中的每个的时间,这意味着,实例化controlExecuted在一个窗口中是不一样的对象作为controlExecuted在另一个窗口。

There are two broad ways to share code in an extension: 在扩展程序中共享代码有两种方法:

  • Create an XPCOM component . 创建一个XPCOM组件 This is the classic, more difficult (but very powerful) method of sharing code in a browser extension. 这是在浏览器扩展中共享代码的经典,更难(但非常强大)的方法。

  • Create a JavaScript code module (JSM). 创建JavaScript代码模块 (JSM)。 In short: 简而言之:

    JavaScript code modules are a concept introduced in Gecko 1.9 and can be used for sharing code between different privileged scopes. JavaScript代码模块是Gecko 1.9中引入的概念,可用于在不同的特权范围之间共享代码。 Modules can also be used to create global JavaScript singletons that previously required using JavaScript XPCOM objects. 模块还可用于创建以前需要使用JavaScript XPCOM对象的全局JavaScript单例。

You might also consider setting this flag as a user preference , which each instance of your script can read. 您还可以考虑将此标志设置为用户首选项 ,您的脚本的每个实例都可以读取该首选项 This might be the easiest approach for such a simple use case. 对于这样一个简单的用例,这可能是最简单的方法。

Here the complete solution to run only one instance of code in a firefox addon using JavaScript code modules . 这里是使用JavaScript代码模块在firefox插件中仅运行一个代码实例的完整解决方案。

// modules/main.jsm
var EXPORTED_SYMBOLS = ["instancesControl"];

var instancesControl = {
    executed : 0,
    windowExecuting : 0,

    get : function(){
        return ++instancesControl.executed;
    },
    reset : function(){
        instancesControl.executed = 0;
    },
    getWindowExecuting : function(){
        return instancesControl.windowExecuting;
    },
    setWindowExecuting : function(id){
        instancesControl.windowExecuting = id;
    }   
};

The main calling code: 主要调用代码:

 // load instancesControl module
Components.utils.import("resource://my-own-alias/main.jsm");

// identify window that will execute the one-instance code
var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var windowID = util.outerWindowID;

// listen load window event 
window.addEventListener("load", function(){
    var appcontent = document.getElementById("appcontent");
    if (appcontent){
        // listen load content (on every tab)
        appcontent.addEventListener("DOMContentLoaded", function docLoader(e){
            appcontent.removeEventListener("DOMContentLoaded", docLoader, false);
            if (instancesControl.get() == 1){
                instancesControl.setWindowExecuting(windowID);

                // this code will run only once no matter
                // how many tabs or windows user opens.

            }
        }, true);
    }
}, false);

// re-init code if executing windows is closed
window.addEventListener("unload", function(){
    if (instancesControl.getWindowExecuting() == windowID){
        instancesControl.reset();
    }
}, false);

Sure that you can improve it. 当然你可以改进它。 Comment using @nomikos if you do. 如果你这样做,请使用@nomikos进行评论。
THX. 谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM