diff options
author | Alessio Vanni <vannilla@firemail.cc> | 2019-02-19 21:06:09 +0100 |
---|---|---|
committer | Alessio Vanni <vannilla@firemail.cc> | 2019-02-19 21:06:09 +0100 |
commit | fe2f8acc8210c2ddead4621797b47106a9b38f5b (patch) | |
tree | 5fb103d45d7e4345f56fc068ce8173b82fa7051f /bootstrap.js | |
download | ematrix-fe2f8acc8210c2ddead4621797b47106a9b38f5b.tar.lz ematrix-fe2f8acc8210c2ddead4621797b47106a9b38f5b.tar.xz ematrix-fe2f8acc8210c2ddead4621797b47106a9b38f5b.zip |
Fork uMatrix
Pretty much just changing the name and the copyright.
Diffstat (limited to 'bootstrap.js')
-rw-r--r-- | bootstrap.js | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/bootstrap.js b/bootstrap.js new file mode 100644 index 0000000..513f3aa --- /dev/null +++ b/bootstrap.js @@ -0,0 +1,246 @@ +/******************************************************************************* + + η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/}. + + uMatrix Home: https://github.com/gorhill/uMatrix +*/ + +/* global ADDON_UNINSTALL, APP_SHUTDOWN */ +/* exported startup, shutdown, install, uninstall */ + +'use strict'; + +/******************************************************************************/ + +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +// Accessing the context of the background page: +// var win = Services.appShell.hiddenDOMWindow.document.querySelector('iframe[src*=umatrix]').contentWindow; + +let windowlessBrowser = null; +let windowlessBrowserPL = null; +let bgProcess = null; +let version; +const hostName = 'umatrix'; +const restartListener = { + get messageManager() { + return Cc['@mozilla.org/parentprocessmessagemanager;1'] + .getService(Ci.nsIMessageListenerManager); + }, + + receiveMessage: function() { + shutdown(); + startup(); + } +}; + +/******************************************************************************/ + +// https://github.com/gorhill/uBlock/issues/2493 +// Fix by https://github.com/gijsk +// imported from https://github.com/gorhill/uBlock/pull/2497 + +function startup(data/*, reason*/) { + if ( data !== undefined ) { + version = data.version; + } + + // Already started? + if ( bgProcess !== null ) { + return; + } + + waitForHiddenWindow(); +} + +function createBgProcess(parentDocument) { + bgProcess = parentDocument.documentElement.appendChild( + parentDocument.createElementNS('http://www.w3.org/1999/xhtml', 'iframe') + ); + bgProcess.setAttribute( + 'src', + 'chrome://' + hostName + '/content/background.html#' + version + ); + + // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIMessageListenerManager#addMessageListener%28%29 + // "If the same listener registers twice for the same message, the + // "second registration is ignored." + restartListener.messageManager.addMessageListener( + hostName + '-restart', + restartListener + ); +} + +function getWindowlessBrowserFrame(appShell) { + windowlessBrowser = appShell.createWindowlessBrowser(true); + windowlessBrowser.QueryInterface(Ci.nsIInterfaceRequestor); + let webProgress = windowlessBrowser.getInterface(Ci.nsIWebProgress); + let XPCOMUtils = Cu.import('resource://gre/modules/XPCOMUtils.jsm', null).XPCOMUtils; + windowlessBrowserPL = { + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIWebProgressListener, + Ci.nsIWebProgressListener2, + Ci.nsISupportsWeakReference + ]), + onStateChange: function(wbp, request, stateFlags, status) { + if ( !request ) { return; } + if ( stateFlags & Ci.nsIWebProgressListener.STATE_STOP ) { + webProgress.removeProgressListener(windowlessBrowserPL); + windowlessBrowserPL = null; + createBgProcess(windowlessBrowser.document); + } + } + }; + webProgress.addProgressListener(windowlessBrowserPL, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT); + windowlessBrowser.document.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='" + hostName + "-win'/>"; +} + +function waitForHiddenWindow() { + let appShell = Cc['@mozilla.org/appshell/appShellService;1'] + .getService(Ci.nsIAppShellService); + + let isReady = function() { + var hiddenDoc; + + try { + hiddenDoc = appShell.hiddenDOMWindow && + appShell.hiddenDOMWindow.document; + } catch (ex) { + } + + // Do not test against `loading`: it does appear `readyState` could be + // undefined if looked up too early. + if ( !hiddenDoc || hiddenDoc.readyState !== 'complete' ) { + return false; + } + + // In theory, it should be possible to create a windowless browser + // immediately, without waiting for the hidden window to have loaded + // completely. However, in practice, on Windows this seems to lead + // to a broken Firefox appearance. To avoid this, we only create the + // windowless browser here. We'll use that rather than the hidden + // window for the actual background page (windowless browsers are + // also what the webextension implementation in Firefox uses for + // background pages). + let { Services } = Cu.import('resource://gre/modules/Services.jsm', null); + if ( Services.vc.compare(Services.appinfo.platformVersion, '27') >= 0 ) { + getWindowlessBrowserFrame(appShell); + } else { + createBgProcess(hiddenDoc); + } + return true; + }; + + if ( isReady() ) { + return; + } + + // https://github.com/gorhill/uBlock/issues/749 + // Poll until the proper environment is set up -- or give up eventually. + // We poll frequently early on but relax poll delay as time pass. + + let tryDelay = 5; + let trySum = 0; + // https://trac.torproject.org/projects/tor/ticket/19438 + // Try for a longer period. + let tryMax = 600011; + let timer = Cc['@mozilla.org/timer;1'] + .createInstance(Ci.nsITimer); + + let checkLater = function() { + trySum += tryDelay; + if ( trySum >= tryMax ) { + timer = null; + return; + } + timer.init(timerObserver, tryDelay, timer.TYPE_ONE_SHOT); + tryDelay *= 2; + if ( tryDelay > 503 ) { + tryDelay = 503; + } + }; + + var timerObserver = { + observe: function() { + timer.cancel(); + if ( isReady() ) { + timer = null; + } else { + checkLater(); + } + } + }; + + checkLater(); +} + +/******************************************************************************/ + +function shutdown(data, reason) { + if ( reason === APP_SHUTDOWN ) { + return; + } + + if ( bgProcess !== null ) { + bgProcess.parentNode.removeChild(bgProcess); + bgProcess = null; + } + + if ( windowlessBrowser !== null ) { + // close() does not exist for older versions of Firefox. + if ( typeof windowlessBrowser.close === 'function' ) { + windowlessBrowser.close(); + } + windowlessBrowser = null; + windowlessBrowserPL = null; + } + + if ( data === undefined ) { + return; + } + + // Remove the restartObserver only when the extension is being disabled + restartListener.messageManager.removeMessageListener( + hostName + '-restart', + restartListener + ); +} + +/******************************************************************************/ + +function install() { + // https://bugzil.la/719376 + Cc['@mozilla.org/intl/stringbundle;1'] + .getService(Ci.nsIStringBundleService) + .flushBundles(); +} + +/******************************************************************************/ + +function uninstall(data, aReason) { + if ( aReason !== ADDON_UNINSTALL ) { + return; + } + // To cleanup vAPI.localStorage in vapi-common.js, aka + // "extensions.umatrix.*" in `about:config`. + Cu.import('resource://gre/modules/Services.jsm', null) + .Services.prefs.getBranch('extensions.' + hostName + '.') + .deleteBranch(''); +} + +/******************************************************************************/ |