diff options
author | Alessio Vanni <vannilla@firemail.cc> | 2019-07-19 16:11:45 +0200 |
---|---|---|
committer | Alessio Vanni <vannilla@firemail.cc> | 2019-07-19 16:11:45 +0200 |
commit | 1ec6e70fc1df5f804f8ec254055fce3775123785 (patch) | |
tree | 03910671df22785ea18be4415eb6c14d8553d329 /js/vapi-window.js | |
parent | a835d88e7fb3b5f01614985958bc68dd7f9e78cc (diff) | |
parent | acd097e4733c106a15815c90e21c00d0c545e042 (diff) | |
download | ematrix-1ec6e70fc1df5f804f8ec254055fce3775123785.tar.lz ematrix-1ec6e70fc1df5f804f8ec254055fce3775123785.tar.xz ematrix-1ec6e70fc1df5f804f8ec254055fce3775123785.zip |
Merge branch 'rewrite-vapi'
Diffstat (limited to 'js/vapi-window.js')
-rw-r--r-- | js/vapi-window.js | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/js/vapi-window.js b/js/vapi-window.js new file mode 100644 index 0000000..e01dc7a --- /dev/null +++ b/js/vapi-window.js @@ -0,0 +1,183 @@ +/******************************************************************************* + + ηMatrix - a browser extension to black/white list requests. + Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors + Copyright (C) 2019 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; + })(); +})(); |