我的卸载器的实现是否合适?

时间:2014-07-21 11:08:52

标签: firefox-addon

我在这里重新阅读这篇文章:https://stackoverflow.com/a/24473888/1828637

并担心我是否做得对。这就是我卸货的方式:

所以我在每个窗口设置一些东西。并在关机时卸载它们。 (我不会在窗口关闭时卸载,我还没有找到需要,因为当它关闭时,我添加到它的所有内容都与关闭一起[例如我的变异观察者])。

下面的所有代码都是理论上的,变异的东西就是例子,因此可能存在拼写错误或错误。我想知道它背后的想法是否合适:

var unloadersOnShutdown = [];
var unloadersOnClose = [];

function startup() {
        let DOMWindows = Services.wm.getEnumerator(null);
        while (DOMWindows.hasMoreElements()) {
            let aDOMWindow = DOMWindows.getNext();
            var worker = new winWorker(aDOMWindow);
            unloadersOnShutdown.push({DOMWindow: aDOMWindow, fn: worker.destroy});
        }
}

function shutdown() {
        Array.forEach.call(unloadersOnShutdown, function(obj) {
            //should probably test if obj.DOMWindow exists/is open, but just put it in try-ctach
            try {
                obj.fn();
            } catch(ex) {
                //window was probably closed
                console.warn('on shutdown unlaoder:', ex);
            }
        });
}

function winWorker(aDOMWindow) {
    this.DOMWindow = aDOMWindow;
    this.init();
}

winWorker.prototype = {
    init: function() {
        this.gMutationObserver = new this.DOMWindow.MutationObserver(gMutationFunc.bind(this));
        this.myElement = this.DOMWindow.querySelector('#myXulEl');
        this.gMutationObserver.observe(this.myElement, gMutationConfig);
        if (this.DOMWindow.gBrowser && this.DOMWindow.gBrowser.tabContainer) {
            this.onTabSelectBinded = this.onTabSelect.bind(this);
            this.gBrowser.tabContainer.addEventListener('TabSelect', this.onTabSelectBinded, false);
        }
    },
    destroy: function() {
        this.gMutationObserver.disconnect();
        if (this.onTabSelectBinded) {
            this.gBrowser.tabContainer.removeEventListener('TabSelect', this.onTabSelectBinded, false);
        }
    },
    onTabSelect: function() {
        console.log('tab selected = ', thisDOMWindow.gBrowser.selectedTab);
    }
};

var windowListener = {
    onOpenWindow: function (aXULWindow) {},
    onCloseWindow: function (aXULWindow) {
        var DOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
        for (var i=0; i<unloadersOnClose.length; i++) {
            if (unloadersOnClose.DOMWindow == DOMWindow) {
                try {
                    unloadersOnClose.fn();
                } catch(ex) {
                    console.warn('on close unloader:', ex);
                }
                unloadersOnClose.splice(i, 1);
                i--;
            }
        }
    },
    onWindowTitleChange: function (aXULWindow, aNewTitle) {},
}

我认为一个问题是我没有使用DOMWindow的弱引用,但我不确定。

1 个答案:

答案 0 :(得分:2)

围绕卸载程序的想法似乎一般都没问题,但非常有限(仅适用于Windows)。

缺乏实施。例如。有一个很大的肥胖小虫:

unloadersOnShutdown.push({DOMWindow: aDOMWindow, fn: worker.destroy});
// and
obj.fn();
// or
unloadersOnClose.fn();

这会使用错误的winWorker.prototype.destroy来调用this

i++ / i--循环也看起来,嗯...... "interesting"?!

另外,请记住可能存在微妙的泄漏,因此您应该考虑并测试Zombie compartments。 窗口不仅可以泄漏附件的部分内容(例如bootstrap.js),而且还可以通过在附加组件中保留引用来泄漏关闭的窗口。当然,它不仅仅是你需要关心的窗户,而且还包括观察者,其他类型的(XPCOM)听众等。