简体   繁体   English

如何识别浏览器元素[XUL / firefox]的标签关闭事件

[英]How to identify tab close event for browser element [XUL/firefox]

I work on an addon that observes all the http requests and populate some info corresponding to each tab. 我在一个插件上工作,该插件可观察所有http请求并填充与每个选项卡相对应的一些信息。 I want to clear the data for the tab which I close. 我想清除我关闭的标签的数据。 However, I can't get to identiy tab close event in a cleaner/saner way. 但是,我无法以更清洁/更整洁的方式确定选项卡关闭事件。 So I have the contentWindow (LoadContext -> associatedWindow) for which the request was made, and the browser for that content window (which is for the tab). 因此,我有针对其发出请求的contentWindow (LoadContext-> relatedWindow),以及该内容窗口(用于选项卡)的browser

  1. I realized that to do a browser.addEventListener , I will have to listen for DOMNodeRemoved event - which is deprecated as per MDN (and should rather use mutation observers). 我意识到要做一个browser.addEventListener ,我将不得不监听DOMNodeRemoved事件- 根据MDN不推荐使用 (应该使用变异观察器)。 Moreover, I won't get the events when a popup window is closed. 而且,当弹出窗口关闭时,我不会收到事件。
  2. If I do a contentWindow.addEventListener and look for unload event, the results are quite unpredictable. 如果我执行contentWindow.addEventListener并查找unload事件,则结果将是不可预测的。 Some times, I don't get the events at all. 有时候,我根本不了解事件。
  3. If I get this tab element from gBrowser.tabs and listen for TabClose event, I can get all close events for the tab. 如果我从gBrowser.tabs获取此tab元素并侦听TabClose事件,则可以获取该标签的所有close事件。 But then again, it won't inform of any popup-window closes (although I do get a tab element for the popup-window) 但是话又说回来,它不会通知任何弹出窗口关闭(尽管我确实获得了弹出窗口的tab元素)

So what is the easiest/cleanest way to know any tab/popup-window close ? 那么,什么是最简单/最干净的方法来了解任何选项卡/弹出窗口关闭的呢? I don't use the addon SDK, btw. 我不使用插件SDK,顺便说一句。

EDIT : Looking for a simpler, valid-for-all-cases solution. 编辑:寻找一个更简单,适用于所有情况的解决方案。 ie. 即。 I get notified of close event be it a tab or a popup-window (or any other types of windows if they exist!). 我会收到关闭事件的通知,它是选项卡还是弹出窗口(或其他任何类型的窗口,如果它们存在的话!)。 I believe that might be possible given that I hold a browser element which contains the DOM window, and the DOM get removed (unloaded) upon a close. 我相信,如果我拥有一个包含DOM窗口的浏览器元素,并且在关闭时DOM被删除(卸载),这可能是可行的。

EDIT-2 : Realized that all the problem was due to one thing : there is no TabClose event from Firefox when the last tab closes (which is a window close). EDIT-2:意识到所有问题都是由于一件事:当最后一个选项卡关闭时(这是一个窗口关闭),Firefox中没有TabClose事件。 Life would have been much easier if we were notified of the tabs that get closed when a window closes. 如果通知我们在关闭窗口时关闭的选项卡,生活会容易得多。 Any ways, I will go with a modified version of @Noitidart's solution - to have a separate window listener, in addition to the TabClose listener. 无论如何,我都会使用@Noitidart解决方案的修改版本-除了TabClose侦听器之外,还有一个单独的窗口侦听器。 And find the tab elements in it and do my clean up. 并在其中找到tab元素并进行清理。 Sigh! 叹! Will do a bit more search in this, and see if this qualifies for a bug/enhancement. 将对此进行更多搜索,并查看是否符合错误/增强的条件。 Thanks to @Noitidart and @Blargh for their suggestions. 感谢@Noitidart和@Blargh的建议。

I say hold a reference to the tab. 我说保留对选项卡的引用。 This is how i do it in addons MouseControl and WorkspaceHopper. 这是我在插件MouseControl和WorkspaceHopper中执行的操作。

so like check: 就像检查:

if (tab.parentNode) {

}

do a try catch too, if it catches then tab obviously doesnt exist. 也尝试捕获,如果捕获,则制表符显然不存在。

but for tabClose you might as well use the tabclose event and for window popup, use the windowsMediator listner and listen to onWindowClose 但是对于tabClos​​e,您也可以使用tabclose事件;对于窗口弹出,请使用windowsMediator列表器,并监听onWindowClose

var windowListener = {
    //DO NOT EDIT HERE
    onOpenWindow: function (aXULWindow) {
        // Wait for the window to finish loading
        let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
        aDOMWindow.addEventListener('load', function () {
            aDOMWindow.removeEventListener('load', arguments.callee, false);
            windowListener.loadIntoWindow(aDOMWindow);
        }, false);
    },
    onCloseWindow: function (aXULWindow) {},
    onWindowTitleChange: function (aXULWindow, aNewTitle) {},
    register: function () {

        // Load into any existing windows
        let DOMWindows = Services.wm.getEnumerator(null);
        while (DOMWindows.hasMoreElements()) {
            let aDOMWindow = DOMWindows.getNext();
            windowListener.loadIntoWindow(aDOMWindow);
        }
        // Listen to new windows
        Services.wm.addListener(windowListener);
    },
    unregister: function () {
        // Unload from any existing windows
        let DOMWindows = Services.wm.getEnumerator(null);
        while (DOMWindows.hasMoreElements()) {
            let aDOMWindow = DOMWindows.getNext();
            windowListener.unloadFromWindow(aDOMWindow);
        }

        //Stop listening so future added windows dont get this attached
        Services.wm.removeListener(windowListener);
    },
    //END - DO NOT EDIT HERE
    loadIntoWindow: function (aDOMWindow) {
        if (!aDOMWindow) {
            return;
        }

        //do stuff here

    },
    unloadFromWindow: function (aDOMWindow) {
        if (!aDOMWindow) {
            return;
        }
        //do stuff here
    }
};

Here's my modified version of @Noitidart's answer. 这是我对@Noitidart答案的修改版本。 I use an expando property on browser (eg: _myextensionTabId ) to index my cached array. 我在browser上使用expando属性(例如_myextensionTabId )来索引我的缓存数组。

var WindowListener = {
/* Same as @Noitidart's listener */
  onOpenWindow : function(xulWindow) {
    /* Get DOM window, call other window specific modules init */
    myExtension.initWindow(domWindow);
    myHttpObserver.initWindow(domWindow);
  },
  onCloseWindow: function(xulWindow) {
    /* Get DOM window, call other window specific modules uninit */
    myExtension.uninitWindow(domWindow);
    myHttpObserver.uninitWindow(domWindow);
  },
};

var myHttpObserver = {
    ..  
    initWindow: function(window) {
      window.gBrowser.tabContainer
              .addEventListener('TabClose', tabClosed, false);
    }, 

    uninitWindow: function(window) {
      dump ("Uninit window http observer\n");
      window.gBrowser.tabContainer
                .removeEventListener('TabClose', tabClosed);
      for (var browser of window.gBrowser.browsers) {
        if (browser._myextensionTabId) {
          // Do any cleanup.
        }
      }
    },
  .. 
    /* Other http observer stuff, methods that sets the expando property etc. */
};

function tabClosed(e) {
  var browser = Services.wm.getMostRecentWindow("navigator:browser")
                           .gBrowser.getBrowserForTab(e.target);
  dump("Tab closed. \n");
  if (browser._myextensionTabId) {
    dump("My extension tab id : " + browser._myextensionTabId);
    // Do any cleanup
  }
}

For a one solution fits tab and window you can try window observers: https://developer.mozilla.org/en-US/docs/Observer_Notifications#Windows 对于适合标签和窗口的一种解决方案,您可以尝试使用窗口观察器: https : //developer.mozilla.org/zh-CN/docs/Observer_Notifications#Windows

Probably want to use the outer-window-destroyed observer, I think each browser element within tab is an outer window. 可能想使用outer-window-destroyedouter-window-destroyed观察器,我认为tab中的每个浏览器元素都是一个外部窗口。 I'm not sure. 我不确定。 It might trigger everytime the document changes though, so you would have to QI and get the tab and check if its closed/closing or still open. 但是,它可能会在每次文档更改时触发,因此您必须使用QI并获取选项卡,并检查其关闭/关闭还是仍处于打开状态。

Try it out, share with us what you learn, I'm very interested. 尝试一下,与我们分享您学到的知识,我对此非常感兴趣。 On close i think it gets destroyed. 近距离来看,我认为它被摧毁了。

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

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