aboutsummaryrefslogtreecommitdiffstats
path: root/bootstrap.js
diff options
context:
space:
mode:
authorAlessio Vanni <vannilla@firemail.cc>2019-02-19 21:06:09 +0100
committerAlessio Vanni <vannilla@firemail.cc>2019-02-19 21:06:09 +0100
commitfe2f8acc8210c2ddead4621797b47106a9b38f5b (patch)
tree5fb103d45d7e4345f56fc068ce8173b82fa7051f /bootstrap.js
downloadematrix-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.js246
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('');
+}
+
+/******************************************************************************/