/******************************************************************************* ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ 'use strict'; /******************************************************************************/ (function () { vAPI.window = (function () { let windowToIdMap = new Map(); let windowIdGenerator = 1; let api = { onOpenWindow: null, onCloseWindow: null }; // https://github.com/gorhill/uMatrix/issues/586 This is // necessary hack because on SeaMonkey 2.40, for unknown // reasons private windows do not have the attribute // `windowtype` set to `navigator:browser`. As a fallback, the // code here will also test whether the id attribute is // `main-window`. api.toBrowserWindow = function (win) { let docElement = win && win.document && win.document.documentElement; if (!docElement) { return null; } if (vAPI.thunderbird) { return docElement.getAttribute('windowtype') === 'mail:3pane' ? win : null; } return docElement.getAttribute('windowtype') === 'navigator:browser' || docElement.getAttribute('id') === 'main-window' ? win : null; }; api.getWindows = function () { return windowToIdMap.keys(); }; api.idFromWindow = function (win) { return windowToIdMap.get(win) || 0; }; api.getCurrentWindow = function () { return this.toBrowserWindow(Services.wm.getMostRecentWindow(null)); }; let addWindow = function (win) { if (!win || windowToIdMap.has(win)) { return; } windowToIdMap.set(win, windowIdGenerator++); if (typeof api.onOpenWindow === 'function') { api.onOpenWindow(win); } }; let removeWindow = function (win) { if (!win || windowToIdMap.delete(win) !== true) { return; } if (typeof api.onCloseWindow === 'function') { api.onCloseWindow(win); } }; // https://github.com/gorhill/uMatrix/issues/357 // Use nsIWindowMediator for being notified of opened/closed windows. let listeners = { onOpenWindow: function (aWindow) { let win; try { win = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); } catch (e) { // Ignore } addWindow(win); }, onCloseWindow: function (aWindow) { let win; try { win = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); } catch (e) { // Ignore } removeWindow(win); }, observe: function (aSubject, topic) { let win; try { win = aSubject.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); } catch (e) { // Ignore } if (!win) { return; } switch (topic) { case 'domwindowopened': addWindow(win); break; case 'domwindowclosed': removeWindow(win); break; default: console.error('unknown observer topic'); break; } } }; (function() { let winumerator; winumerator = Services.wm.getEnumerator(null); while (winumerator.hasMoreElements()) { let win = winumerator.getNext(); if (!win.closed) { windowToIdMap.set(win, windowIdGenerator++); } } winumerator = Services.ww.getWindowEnumerator(); while (winumerator.hasMoreElements()) { let win = winumerator.getNext() .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); if (!win.closed) { windowToIdMap.set(win, windowIdGenerator++); } } Services.wm.addListener(listeners); Services.ww.registerNotification(listeners); })(); vAPI.addCleanUpTask(function() { Services.wm.removeListener(listeners); Services.ww.unregisterNotification(listeners); windowToIdMap.clear(); }); return api; })(); })();