aboutsummaryrefslogtreecommitdiffstats
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/asset-viewer.js21
-rw-r--r--js/background.js94
-rw-r--r--js/browsercache.js28
-rw-r--r--js/cloud-ui.js140
-rw-r--r--js/contentscript-start.js72
-rw-r--r--js/contentscript.js517
-rw-r--r--js/cookies.js464
-rw-r--r--js/dashboard-common.js16
-rw-r--r--js/dashboard.js24
-rw-r--r--js/hosts-files.js407
-rw-r--r--js/httpsb.js8
-rw-r--r--js/i18n.js92
-rw-r--r--js/logger-ui.js706
-rw-r--r--js/logger.js40
-rw-r--r--js/matrix.js16
-rw-r--r--js/messaging.js17
-rw-r--r--js/pagestats.js6
-rw-r--r--js/popup.js1134
-rw-r--r--js/settings.js139
-rw-r--r--js/start.js64
-rw-r--r--js/storage.js8
-rw-r--r--js/tab.js658
-rw-r--r--js/traffic.js10
-rw-r--r--js/user-rules.js280
-rw-r--r--js/vapi-background.js112
-rw-r--r--js/vapi-core.js9
-rw-r--r--js/vapi-messaging.js2
-rw-r--r--js/vapi-net.js5
28 files changed, 2425 insertions, 2664 deletions
diff --git a/js/asset-viewer.js b/js/asset-viewer.js
index 1d88459..0185ff1 100644
--- a/js/asset-viewer.js
+++ b/js/asset-viewer.js
@@ -23,25 +23,20 @@
'use strict';
-/******************************************************************************/
-
(function() {
-
- var onAssetContentReceived = function(details) {
+ let onAssetContentReceived = function (details) {
document.getElementById('content').textContent =
details && (details.content || '');
};
- var q = window.location.search;
- var matches = q.match(/^\?url=([^&]+)/);
- if ( !matches || matches.length !== 2 ) {
+ let q = window.location.search;
+ let matches = q.match(/^\?url=([^&]+)/);
+ if (!matches || matches.length !== 2) {
return;
}
- vAPI.messaging.send(
- 'asset-viewer.js',
- { what : 'getAssetContent', url: matches[1] },
- onAssetContentReceived
- );
-
+ vAPI.messaging.send('asset-viewer.js', {
+ what : 'getAssetContent',
+ url: matches[1]
+ }, onAssetContentReceived);
})();
diff --git a/js/background.js b/js/background.js
index 07065b7..7ac9ef2 100644
--- a/js/background.js
+++ b/js/background.js
@@ -23,25 +23,19 @@
'use strict';
-/******************************************************************************/
+var ηMatrix = (function () {
+ Cu.import('chrome://ematrix/content/lib/LiquidDict.jsm');
-var ηMatrix = (function() { // jshint ignore:line
+ let oneSecond = 1000;
+ let oneMinute = 60 * oneSecond;
+ let oneHour = 60 * oneMinute;
+ let oneDay = 24 * oneHour;
- /******************************************************************************/
-
- var oneSecond = 1000;
- var oneMinute = 60 * oneSecond;
- var oneHour = 60 * oneMinute;
- var oneDay = 24 * oneHour;
-
- /******************************************************************************/
- /******************************************************************************/
-
- var _RequestStats = function() {
+ let _RequestStats = function () {
this.reset();
};
- _RequestStats.prototype.reset = function() {
+ _RequestStats.prototype.reset = function () {
this.all =
this.doc =
this.frame =
@@ -54,21 +48,19 @@ var ηMatrix = (function() { // jshint ignore:line
this.cookie = 0;
};
- /******************************************************************************/
-
- var RequestStats = function() {
- this.allowed = new _RequestStats();
- this.blocked = new _RequestStats();
+ var RequestStats = function () {
+ this.allowed = new _RequestStats ();
+ this.blocked = new _RequestStats ();
};
- RequestStats.prototype.reset = function() {
+ RequestStats.prototype.reset = function () {
this.blocked.reset();
this.allowed.reset();
};
- RequestStats.prototype.record = function(type, blocked) {
+ RequestStats.prototype.record = function (type, blocked) {
// Remember: always test against **false**
- if ( blocked !== false ) {
+ if (blocked !== false) {
this.blocked[type] += 1;
this.blocked.all += 1;
} else {
@@ -77,35 +69,32 @@ var ηMatrix = (function() { // jshint ignore:line
}
};
- var requestStatsFactory = function() {
+ var requestStatsFactory = function () {
return new RequestStats();
};
- /*******************************************************************************
-
- SVG-based icons below were extracted from
- fontawesome-webfont.svg v4.7. Excerpt of copyright notice at
- the top of the file:
-
- > Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
- > By ,,,
- > Copyright Dave Gandy 2016. All rights reserved.
+ /**
+ SVG-based icons below were extracted from
+ fontawesome-webfont.svg v4.7. Excerpt of copyright notice at
+ the top of the file:
- Excerpt of the license information in the fontawesome CSS
- file bundled with the package:
+ > Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
+ > By ,,,
+ > Copyright Dave Gandy 2016. All rights reserved.
- > Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
- > License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ Excerpt of the license information in the fontawesome CSS
+ file bundled with the package:
- Font icons:
- - glyph-name: "external_link"
+ > Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ > License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ Font icons:
+ - glyph-name: "external_link"
*/
var rawSettingsDefault = {
disableCSPReportInjection: false,
- placeholderBackground:
- [
+ placeholderBackground: [
'url("data:image/png;base64,',
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAK',
'CAAAAACoWZBhAAAABGdBTUEAALGPC/xh',
@@ -125,8 +114,7 @@ var ηMatrix = (function() { // jshint ignore:line
imagePlaceholderBackground: 'default',
imagePlaceholderBorder: 'default',
framePlaceholder: true,
- framePlaceholderDocument:
- [
+ framePlaceholderDocument: [
'<html><head>',
'<meta charset="utf-8">',
'<style>',
@@ -160,8 +148,6 @@ var ηMatrix = (function() { // jshint ignore:line
framePlaceholderBackground: 'default',
};
- /******************************************************************************/
-
return {
onBeforeStartQueue: [],
@@ -186,7 +172,8 @@ var ηMatrix = (function() { // jshint ignore:line
popupCollapseBlacklistedDomains: false,
popupScopeLevel: 'domain',
processHyperlinkAuditing: true,
- processReferer: false
+ processReferer: false,
+ disableUpdateIcon: false,
},
rawSettingsDefault: rawSettingsDefault,
@@ -207,8 +194,8 @@ var ηMatrix = (function() { // jshint ignore:line
liveHostsFiles: {
},
- // urls stats are kept on the back burner while waiting to be reactivated
- // in a tab or another.
+ // urls stats are kept on the back burner while waiting to be
+ // reactivated in a tab or another.
pageStores: {},
pageStoresToken: 0,
pageStoreCemetery: {},
@@ -217,7 +204,8 @@ var ηMatrix = (function() { // jshint ignore:line
tMatrix: null,
pMatrix: null,
- ubiquitousBlacklist: null,
+ ubiquitousBlacklist: new LiquidDict(),
+ ubiquitousWhitelist: new LiquidDict(),
// various stats
requestStatsFactory: requestStatsFactory,
@@ -233,14 +221,6 @@ var ηMatrix = (function() { // jshint ignore:line
// record what the browser is doing behind the scene
behindTheSceneScope: 'behind-the-scene',
- noopFunc: function(){},
-
- // so that I don't have to care for last comma
- dummy: 0
+ noopFunc: function () {},
};
-
- /******************************************************************************/
-
})();
-
-/******************************************************************************/
diff --git a/js/browsercache.js b/js/browsercache.js
index 1360f92..bc2fdd2 100644
--- a/js/browsercache.js
+++ b/js/browsercache.js
@@ -21,46 +21,36 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global ηMatrix */
-
'use strict';
-/******************************************************************************/
-
-(function() {
-
- /******************************************************************************/
-
+(function () {
// Browser data jobs
- var clearCache = function() {
+ let clearCache = function () {
vAPI.setTimeout(clearCache, 15 * 60 * 1000);
var ηm = ηMatrix;
- if ( !ηm.userSettings.clearBrowserCache ) {
+ if (!ηm.userSettings.clearBrowserCache) {
return;
}
ηm.clearBrowserCacheCycle -= 15;
- if ( ηm.clearBrowserCacheCycle > 0 ) {
+ if (ηm.clearBrowserCacheCycle > 0) {
return;
}
vAPI.browser.data.clearCache();
ηm.clearBrowserCacheCycle = ηm.userSettings.clearBrowserCacheAfter;
- ηm.browserCacheClearedCounter++;
+ ++ηm.browserCacheClearedCounter;
// TODO: i18n
- ηm.logger.writeOne('', 'info', vAPI.i18n('loggerEntryBrowserCacheCleared'));
+ ηm.logger.writeOne('', 'info',
+ vAPI.i18n('loggerEntryBrowserCacheCleared'));
- //console.debug('clearBrowserCacheCallback()> vAPI.browser.data.clearCache() called');
+ // console.debug('clearBrowserCacheCallback()> '
+ // + 'vAPI.browser.data.clearCache() called');
};
vAPI.setTimeout(clearCache, 15 * 60 * 1000);
-
- /******************************************************************************/
-
})();
-
-/******************************************************************************/
diff --git a/js/cloud-ui.js b/js/cloud-ui.js
index 0f81833..fed262a 100644
--- a/js/cloud-ui.js
+++ b/js/cloud-ui.js
@@ -21,16 +21,9 @@
uMatrix Home: https://github.com/gorhill/uBlock
*/
-/* global uDom */
-
'use strict';
-/******************************************************************************/
-
-(function() {
-
- /******************************************************************************/
-
+(function () {
self.cloud = {
options: {},
datakey: '',
@@ -39,22 +32,18 @@
onPull: null
};
- /******************************************************************************/
-
- var widget = uDom.nodeFromId('cloudWidget');
- if ( widget === null ) {
+ let widget = uDom.nodeFromId('cloudWidget');
+ if (widget === null) {
return;
}
self.cloud.datakey = widget.getAttribute('data-cloud-entry') || '';
- if ( self.cloud.datakey === '' ) {
+ if (self.cloud.datakey === '') {
return;
}
- /******************************************************************************/
-
- var onCloudDataReceived = function(entry) {
- if ( typeof entry !== 'object' || entry === null ) {
+ let onCloudDataReceived = function (entry) {
+ if (typeof entry !== 'object' || entry === null) {
return;
}
@@ -63,7 +52,7 @@
uDom.nodeFromId('cloudPull').removeAttribute('disabled');
uDom.nodeFromId('cloudPullAndMerge').removeAttribute('disabled');
- var timeOptions = {
+ let timeOptions = {
weekday: 'short',
year: 'numeric',
month: 'short',
@@ -71,85 +60,64 @@
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
- timeZoneName: 'short'
+ timeZoneName: 'short',
};
- var time = new Date(entry.tstamp);
- widget.querySelector('span').textContent =
- entry.source + '\n' +
- time.toLocaleString('fullwide', timeOptions);
+ let time = new Date(entry.tstamp);
+ widget.querySelector('span').textContent = entry.source
+ + '\n'
+ + time.toLocaleString('fullwide', timeOptions);
};
- /******************************************************************************/
-
- var fetchCloudData = function() {
- vAPI.messaging.send(
- 'cloud-ui.js',
- {
- what: 'cloudPull',
- datakey: self.cloud.datakey
- },
- onCloudDataReceived
- );
+ let fetchCloudData = function () {
+ vAPI.messaging.send('cloud-ui.js', {
+ what: 'cloudPull',
+ datakey: self.cloud.datakey
+ }, onCloudDataReceived);
};
- /******************************************************************************/
-
- var pushData = function() {
- if ( typeof self.cloud.onPush !== 'function' ) {
+ let pushData = function () {
+ if (typeof self.cloud.onPush !== 'function') {
return;
}
- vAPI.messaging.send(
- 'cloud-ui.js',
- {
- what: 'cloudPush',
- datakey: self.cloud.datakey,
- data: self.cloud.onPush()
- },
- fetchCloudData
- );
- };
- /******************************************************************************/
+ vAPI.messaging.send('cloud-ui.js', {
+ what: 'cloudPush',
+ datakey: self.cloud.datakey,
+ data: self.cloud.onPush()
+ }, fetchCloudData);
+ };
- var pullData = function(ev) {
- if ( typeof self.cloud.onPull === 'function' ) {
+ let pullData = function (ev) {
+ if (typeof self.cloud.onPull === 'function') {
self.cloud.onPull(self.cloud.data, ev.shiftKey);
}
};
- /******************************************************************************/
-
- var pullAndMergeData = function() {
- if ( typeof self.cloud.onPull === 'function' ) {
+ let pullAndMergeData = function () {
+ if (typeof self.cloud.onPull === 'function') {
self.cloud.onPull(self.cloud.data, true);
}
};
- /******************************************************************************/
-
- var openOptions = function() {
- var input = uDom.nodeFromId('cloudDeviceName');
+ let openOptions = function () {
+ let input = uDom.nodeFromId('cloudDeviceName');
input.value = self.cloud.options.deviceName;
input.setAttribute('placeholder', self.cloud.options.defaultDeviceName);
uDom.nodeFromId('cloudOptions').classList.add('show');
};
- /******************************************************************************/
-
- var closeOptions = function(ev) {
- var root = uDom.nodeFromId('cloudOptions');
- if ( ev.target !== root ) {
+ let closeOptions = function (ev) {
+ let root = uDom.nodeFromId('cloudOptions');
+ if (ev.target !== root) {
return;
}
root.classList.remove('show');
};
- /******************************************************************************/
-
- var submitOptions = function() {
- var onOptions = function(options) {
- if ( typeof options !== 'object' || options === null ) {
+ let submitOptions = function () {
+ let onOptions = function (options) {
+ if (typeof options !== 'object' || options === null) {
return;
}
self.cloud.options = options;
@@ -164,31 +132,29 @@
uDom.nodeFromId('cloudOptions').classList.remove('show');
};
- /******************************************************************************/
-
- var onInitialize = function(options) {
- if ( typeof options !== 'object' || options === null ) {
+ let onInitialize = function (options) {
+ if (typeof options !== 'object' || options === null) {
return;
}
- if ( !options.enabled ) {
+ if (!options.enabled) {
return;
}
self.cloud.options = options;
- var xhr = new XMLHttpRequest();
+ let xhr = new XMLHttpRequest();
xhr.open('GET', 'cloud-ui.html', true);
xhr.overrideMimeType('text/html;charset=utf-8');
xhr.responseType = 'text';
- xhr.onload = function() {
+ xhr.onload = function () {
this.onload = null;
- var parser = new DOMParser(),
- parsed = parser.parseFromString(this.responseText, 'text/html'),
- fromParent = parsed.body;
- while ( fromParent.firstElementChild !== null ) {
- widget.appendChild(
- document.adoptNode(fromParent.firstElementChild)
- );
+ let parser = new DOMParser();
+ let parsed = parser.parseFromString(this.responseText, 'text/html');
+ let fromParent = parsed.body;
+
+ while (fromParent.firstElementChild !== null) {
+ widget.appendChild(document
+ .adoptNode(fromParent.firstElementChild));
}
vAPI.i18n.render(widget);
@@ -203,13 +169,13 @@
fetchCloudData();
};
+
xhr.send();
};
- vAPI.messaging.send('cloud-ui.js', { what: 'cloudGetOptions' }, onInitialize);
-
- /******************************************************************************/
+ vAPI.messaging.send('cloud-ui.js', {
+ what: 'cloudGetOptions'
+ }, onInitialize);
// https://www.youtube.com/watch?v=aQFp67VoiDA
-
})();
diff --git a/js/contentscript-start.js b/js/contentscript-start.js
index 3096023..4c320f8 100644
--- a/js/contentscript-start.js
+++ b/js/contentscript-start.js
@@ -23,40 +23,34 @@
'use strict';
-/******************************************************************************/
-/******************************************************************************/
-
// Injected into content pages
-
-(function() {
-
- if ( typeof vAPI !== 'object' ) { return; }
+(function () {
+ if (typeof vAPI !== 'object') {
+ return;
+ }
vAPI.selfWorkerSrcReported = vAPI.selfWorkerSrcReported || false;
var reGoodWorkerSrc = /(?:frame|worker)-src[^;,]+?'none'/;
var handler = function(ev) {
- if (
- ev.isTrusted !== true ||
- ev.originalPolicy.includes('report-uri about:blank') === false
- ) {
+ if (ev.isTrusted !== true
+ || ev.originalPolicy.includes('report-uri about:blank') === false) {
return false;
}
// Firefox and Chromium differs in how they fill the
// 'effectiveDirective' property.
- if (
- ev.effectiveDirective.startsWith('worker-src') === false &&
- ev.effectiveDirective.startsWith('frame-src') === false
- ) {
+ // ηMatrix: what does Pale Moon/Basilisk do?
+ if (ev.effectiveDirective.startsWith('worker-src') === false
+ && ev.effectiveDirective.startsWith('frame-src') === false) {
return false;
}
- // Further validate that the policy violation is relevant to uMatrix:
+ // Further validate that the policy violation is relevant to ηMatrix:
// the event still could have been fired as a result of a CSP header
- // not injected by uMatrix.
- if ( reGoodWorkerSrc.test(ev.originalPolicy) === false ) {
+ // not injected by ηMatrix.
+ if (reGoodWorkerSrc.test(ev.originalPolicy) === false) {
return false;
}
@@ -64,35 +58,31 @@
// However, we do want to report external resources each time.
// TODO: this could eventually lead to duplicated reports for external
// resources if another extension uses the same approach as
- // uMatrix. Think about what could be done to avoid duplicate
+ // ηMatrix. Think about what could be done to avoid duplicate
// reports.
- if ( ev.blockedURI.includes('://') === false ) {
- if ( vAPI.selfWorkerSrcReported ) { return true; }
+ if (ev.blockedURI.includes('://') === false) {
+ if (vAPI.selfWorkerSrcReported) {
+ return true;
+ }
vAPI.selfWorkerSrcReported = true;
}
- vAPI.messaging.send(
- 'contentscript.js',
- {
- what: 'securityPolicyViolation',
- directive: 'worker-src',
- blockedURI: ev.blockedURI,
- documentURI: ev.documentURI,
- blocked: ev.disposition === 'enforce'
- }
- );
+ vAPI.messaging.send('contentscript.js', {
+ what: 'securityPolicyViolation',
+ directive: 'worker-src',
+ blockedURI: ev.blockedURI,
+ documentURI: ev.documentURI,
+ blocked: ev.disposition === 'enforce'
+ });
return true;
};
- document.addEventListener(
- 'securitypolicyviolation',
- function(ev) {
- if ( !handler(ev) ) { return; }
- ev.stopPropagation();
- ev.preventDefault();
- },
- true
- );
-
+ document.addEventListener('securitypolicyviolation', function (ev) {
+ if (!handler(ev)) {
+ return;
+ }
+ ev.stopPropagation();
+ ev.preventDefault();
+ }, true);
})();
diff --git a/js/contentscript.js b/js/contentscript.js
index 650d1be..c304fdf 100644
--- a/js/contentscript.js
+++ b/js/contentscript.js
@@ -21,70 +21,58 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global HTMLDocument, XMLDocument */
-
'use strict';
-/******************************************************************************/
-/******************************************************************************/
-
// Injected into content pages
-(function() {
-
- /******************************************************************************/
-
+(function () {
// https://github.com/chrisaljoudi/uBlock/issues/464
// https://github.com/gorhill/uMatrix/issues/621
- if (
- document instanceof HTMLDocument === false &&
- document instanceof XMLDocument === false
- ) {
+ if (document instanceof HTMLDocument === false
+ && document instanceof XMLDocument === false) {
return;
}
- // This can also happen (for example if script injected into a `data:` URI doc)
- if ( !window.location ) {
+ // This can also happen (for example if script injected into a
+ // `data:` URI doc)
+ if (!window.location) {
return;
}
// This can happen
- if ( typeof vAPI !== 'object' ) {
+ if (typeof vAPI !== 'object') {
//console.debug('contentscript.js > vAPI not found');
return;
}
// https://github.com/chrisaljoudi/uBlock/issues/456
// Already injected?
- if ( vAPI.contentscriptEndInjected ) {
+ if (vAPI.contentscriptEndInjected) {
//console.debug('contentscript.js > content script already injected');
return;
}
vAPI.contentscriptEndInjected = true;
- /******************************************************************************/
- /******************************************************************************/
-
// Executed only once.
-
- (function() {
- var localStorageHandler = function(mustRemove) {
- if ( mustRemove ) {
+ (function () {
+ let localStorageHandler = function (mustRemove) {
+ if (mustRemove) {
window.localStorage.clear();
window.sessionStorage.clear();
}
};
// Check with extension whether local storage must be emptied
- // rhill 2014-03-28: we need an exception handler in case 3rd-party access
- // to site data is disabled.
+ // rhill 2014-03-28: we need an exception handler in case
+ // 3rd-party access to site data is disabled.
// https://github.com/gorhill/httpswitchboard/issues/215
try {
- var hasLocalStorage =
+ let hasLocalStorage =
window.localStorage && window.localStorage.length !== 0;
- var hasSessionStorage =
+ let hasSessionStorage =
window.sessionStorage && window.sessionStorage.length !== 0;
- if ( hasLocalStorage || hasSessionStorage ) {
+
+ if (hasLocalStorage || hasSessionStorage) {
vAPI.messaging.send('contentscript.js', {
what: 'contentScriptHasLocalStorage',
originURL: window.location.origin
@@ -104,140 +92,154 @@
// "There is no way to enumerate or delete the databases available for an origin from this API."
// Ref.: http://www.w3.org/TR/webdatabase/#databases
// }
- }
- catch (e) {
+ } catch (e) {
}
})();
- /******************************************************************************/
- /******************************************************************************/
-
// https://github.com/gorhill/uMatrix/issues/45
-
- var collapser = (function() {
- var resquestIdGenerator = 1,
- processTimer,
- toProcess = [],
- toFilter = [],
- toCollapse = new Map(),
- cachedBlockedMap,
- cachedBlockedMapHash,
- cachedBlockedMapTimer,
- reURLPlaceholder = /\{\{url\}\}/g;
- var src1stProps = {
- 'embed': 'src',
- 'iframe': 'src',
- 'img': 'src',
- 'object': 'data'
+ let collapser = (function () {
+ let resquestIdGenerator = 1;
+ let processTimer;
+ let toProcess = [];
+ let toFilter = [];
+ let toCollapse = new Map();
+ let cachedBlockedMap;
+ let cachedBlockedMapHash;
+ let cachedBlockedMapTimer;
+ let reURLPlaceholder = /\{\{url\}\}/g;
+ let src1stProps = {
+ embed: 'src',
+ iframe: 'src',
+ img: 'src',
+ object: 'data',
};
- var src2ndProps = {
- 'img': 'srcset'
+ let src2ndProps = {
+ img: 'srcset',
};
- var tagToTypeMap = {
+ let tagToTypeMap = {
embed: 'media',
iframe: 'frame',
img: 'image',
- object: 'media'
+ object: 'media',
};
- var cachedBlockedSetClear = function() {
+ let cachedBlockedSetClear = function () {
cachedBlockedMap =
cachedBlockedMapHash =
cachedBlockedMapTimer = undefined;
};
// https://github.com/chrisaljoudi/uBlock/issues/174
- // Do not remove fragment from src URL
- var onProcessed = function(response) {
- if ( !response ) { // This happens if uBO is disabled or restarted.
+ // Do not remove fragment from src URL
+ let onProcessed = function (response) {
+ if (!response) { // This happens if uBO is disabled or restarted.
toCollapse.clear();
return;
}
- var targets = toCollapse.get(response.id);
- if ( targets === undefined ) { return; }
+ let targets = toCollapse.get(response.id);
+ if (targets === undefined) {
+ return;
+ }
+
toCollapse.delete(response.id);
- if ( cachedBlockedMapHash !== response.hash ) {
+
+ if (cachedBlockedMapHash !== response.hash) {
cachedBlockedMap = new Map(response.blockedResources);
cachedBlockedMapHash = response.hash;
- if ( cachedBlockedMapTimer !== undefined ) {
+ if (cachedBlockedMapTimer !== undefined) {
clearTimeout(cachedBlockedMapTimer);
}
- cachedBlockedMapTimer = vAPI.setTimeout(cachedBlockedSetClear, 30000);
+ cachedBlockedMapTimer =
+ vAPI.setTimeout(cachedBlockedSetClear, 30000);
}
- if ( cachedBlockedMap === undefined || cachedBlockedMap.size === 0 ) {
+
+ if (cachedBlockedMap === undefined || cachedBlockedMap.size === 0) {
return;
}
- var placeholders = response.placeholders,
- tag, prop, src, collapsed, docurl, replaced;
+ let placeholders = response.placeholders;
- for ( var target of targets ) {
- tag = target.localName;
- prop = src1stProps[tag];
- if ( prop === undefined ) { continue; }
- src = target[prop];
- if ( typeof src !== 'string' || src.length === 0 ) {
+ for (let target of targets) {
+ let tag = target.localName;
+
+ let prop = src1stProps[tag];
+ if (prop === undefined) {
+ continue;
+ }
+
+ let src = target[prop];
+ if (typeof src !== 'string' || src.length === 0) {
prop = src2ndProps[tag];
- if ( prop === undefined ) { continue; }
+ if (prop === undefined) {
+ continue;
+ }
src = target[prop];
- if ( typeof src !== 'string' || src.length === 0 ) { continue; }
+ if (typeof src !== 'string' || src.length === 0) {
+ continue;
+ }
}
- collapsed = cachedBlockedMap.get(tagToTypeMap[tag] + ' ' + src);
- if ( collapsed === undefined ) { continue; }
- if ( collapsed ) {
+
+ let collapsed = cachedBlockedMap.get(tagToTypeMap[tag]
+ + ' '
+ + src);
+ if (collapsed === undefined) {
+ continue;
+ }
+
+ if (collapsed) {
target.style.setProperty('display', 'none', 'important');
target.hidden = true;
continue;
}
- switch ( tag ) {
+
+ switch (tag) {
case 'iframe':
- if ( placeholders.frame !== true ) { break; }
- docurl =
- 'data:text/html,' +
- encodeURIComponent(
- placeholders.frameDocument.replace(
- reURLPlaceholder,
- src
- )
- );
+ if (placeholders.frame !== true) {
+ break;
+ }
+
+ docurl = 'data:text/html,'
+ + encodeURIComponent(placeholders
+ .frameDocument
+ .replace(reURLPlaceholder, src));
replaced = false;
+
// Using contentWindow.location prevent tainting browser
// history -- i.e. breaking back button (seen on Chromium).
- if ( target.contentWindow ) {
+ if (target.contentWindow) {
try {
target.contentWindow.location.replace(docurl);
replaced = true;
} catch(ex) {
}
}
- if ( !replaced ) {
+
+ if (!replaced) {
target.setAttribute('src', docurl);
}
break;
case 'img':
- if ( placeholders.image !== true ) { break; }
+ if (placeholders.image !== true) {
+ break;
+ }
+
target.style.setProperty('display', 'inline-block');
target.style.setProperty('min-width', '20px', 'important');
target.style.setProperty('min-height', '20px', 'important');
- target.style.setProperty(
- 'border',
- placeholders.imageBorder,
- 'important'
- );
- target.style.setProperty(
- 'background',
- placeholders.imageBackground,
- 'important'
- );
+ target.style.setProperty('border', placeholders.imageBorder,
+ 'important');
+ target.style.setProperty('background',
+ placeholders.imageBackground,
+ 'important');
break;
}
}
};
- var send = function() {
+ let send = function () {
processTimer = undefined;
toCollapse.set(resquestIdGenerator, toProcess);
- var msg = {
+ let msg = {
what: 'lookupBlockedCollapsibles',
id: resquestIdGenerator,
toFilter: toFilter,
@@ -249,95 +251,108 @@
resquestIdGenerator += 1;
};
- var process = function(delay) {
- if ( toProcess.length === 0 ) { return; }
- if ( delay === 0 ) {
- if ( processTimer !== undefined ) {
+ let process = function (delay) {
+ if (toProcess.length === 0) {
+ return;
+ }
+
+ if (delay === 0) {
+ if (processTimer !== undefined) {
clearTimeout(processTimer);
}
send();
- } else if ( processTimer === undefined ) {
+ } else if (processTimer === undefined) {
processTimer = vAPI.setTimeout(send, delay || 47);
}
};
- var add = function(target) {
+ let add = function (target) {
toProcess.push(target);
};
- var addMany = function(targets) {
- var i = targets.length;
- while ( i-- ) {
+ let addMany = function (targets) {
+ for (let i=targets.length-1; i>=0; --i) {
toProcess.push(targets[i]);
}
};
- var iframeSourceModified = function(mutations) {
- var i = mutations.length;
- while ( i-- ) {
+ let iframeSourceModified = function (mutations) {
+ for (let i=mutations.length-1; i>=0; --i) {
addIFrame(mutations[i].target, true);
}
process();
};
- var iframeSourceObserver;
- var iframeSourceObserverOptions = {
+
+ let iframeSourceObserver;
+ let iframeSourceObserverOptions = {
attributes: true,
attributeFilter: [ 'src' ]
};
- var addIFrame = function(iframe, dontObserve) {
+ let addIFrame = function (iframe, dontObserve) {
// https://github.com/gorhill/uBlock/issues/162
// Be prepared to deal with possible change of src attribute.
- if ( dontObserve !== true ) {
- if ( iframeSourceObserver === undefined ) {
- iframeSourceObserver = new MutationObserver(iframeSourceModified);
+ if (dontObserve !== true) {
+ if (iframeSourceObserver === undefined) {
+ iframeSourceObserver =
+ new MutationObserver(iframeSourceModified);
}
- iframeSourceObserver.observe(iframe, iframeSourceObserverOptions);
+ iframeSourceObserver.observe(iframe,
+ iframeSourceObserverOptions);
+ }
+
+ let src = iframe.src;
+ if (src === '' || typeof src !== 'string') {
+ return;
+ }
+ if (src.startsWith('http') === false) {
+ return;
}
- var src = iframe.src;
- if ( src === '' || typeof src !== 'string' ) { return; }
- if ( src.startsWith('http') === false ) { return; }
- toFilter.push({ type: 'frame', url: iframe.src });
+
+ toFilter.push({
+ type: 'frame',
+ url: iframe.src,
+ });
+
add(iframe);
};
- var addIFrames = function(iframes) {
- var i = iframes.length;
- while ( i-- ) {
+ let addIFrames = function (iframes) {
+ for (let i=iframes.length-1; i>=0; --i) {
addIFrame(iframes[i]);
}
};
- var addNodeList = function(nodeList) {
- var node,
- i = nodeList.length;
- while ( i-- ) {
- node = nodeList[i];
- if ( node.nodeType !== 1 ) { continue; }
- if ( node.localName === 'iframe' ) {
+ let addNodeList = function (nodeList) {
+ for (let i=nodeList.length-1; i>=0; --i) {
+ let node = nodeList[i];
+ if (node.nodeType !== 1) {
+ continue;
+ }
+ if (node.localName === 'iframe') {
addIFrame(node);
}
- if ( node.childElementCount !== 0 ) {
+ if (node.childElementCount !== 0) {
addIFrames(node.querySelectorAll('iframe'));
}
}
};
- var onResourceFailed = function(ev) {
- if ( tagToTypeMap[ev.target.localName] !== undefined ) {
+ let onResourceFailed = function (ev) {
+ if (tagToTypeMap[ev.target.localName] !== undefined) {
add(ev.target);
process();
}
};
document.addEventListener('error', onResourceFailed, true);
- vAPI.shutdown.add(function() {
+ vAPI.shutdown.add(function () {
document.removeEventListener('error', onResourceFailed, true);
- if ( iframeSourceObserver !== undefined ) {
+ if (iframeSourceObserver !== undefined) {
iframeSourceObserver.disconnect();
iframeSourceObserver = undefined;
}
- if ( processTimer !== undefined ) {
+ if (processTimer !== undefined) {
clearTimeout(processTimer);
processTimer = undefined;
}
@@ -351,24 +366,21 @@
};
})();
- /******************************************************************************/
- /******************************************************************************/
-
// Observe changes in the DOM
-
// Added node lists will be cumulated here before being processed
- (function() {
+ (function () {
// This fixes http://acid3.acidtests.org/
- if ( !document.body ) { return; }
+ if (!document.body) {
+ return;
+ }
- var addedNodeLists = [];
- var addedNodeListsTimer;
+ let addedNodeLists = [];
+ let addedNodeListsTimer;
- var treeMutationObservedHandler = function() {
+ let treeMutationObservedHandler = function () {
addedNodeListsTimer = undefined;
- var i = addedNodeLists.length;
- while ( i-- ) {
+ for (let i=addedNodeLists.length-1; i>=0; --i) {
collapser.addNodeList(addedNodeLists[i]);
}
collapser.process();
@@ -377,33 +389,33 @@
// https://github.com/gorhill/uBlock/issues/205
// Do not handle added node directly from within mutation observer.
- var treeMutationObservedHandlerAsync = function(mutations) {
- var iMutation = mutations.length,
- nodeList;
- while ( iMutation-- ) {
- nodeList = mutations[iMutation].addedNodes;
- if ( nodeList.length !== 0 ) {
+ let treeMutationObservedHandlerAsync = function (mutations) {
+ for (let i=mutations.length-1; i>=0; --i) {
+ let nodeList = mutations[i].addedNodes;
+ if (nodeList.length !== 0) {
addedNodeLists.push(nodeList);
}
}
- if ( addedNodeListsTimer === undefined ) {
- addedNodeListsTimer = vAPI.setTimeout(treeMutationObservedHandler, 47);
+ if (addedNodeListsTimer === undefined) {
+ addedNodeListsTimer =
+ vAPI.setTimeout(treeMutationObservedHandler, 47);
}
};
// https://github.com/gorhill/httpswitchboard/issues/176
- var treeObserver = new MutationObserver(treeMutationObservedHandlerAsync);
+ let treeObserver =
+ new MutationObserver(treeMutationObservedHandlerAsync);
treeObserver.observe(document.body, {
childList: true,
subtree: true
});
- vAPI.shutdown.add(function() {
- if ( addedNodeListsTimer !== undefined ) {
+ vAPI.shutdown.add(function () {
+ if (addedNodeListsTimer !== undefined) {
clearTimeout(addedNodeListsTimer);
addedNodeListsTimer = undefined;
}
- if ( treeObserver !== null ) {
+ if (treeObserver !== null) {
treeObserver.disconnect();
treeObserver = undefined;
}
@@ -411,9 +423,6 @@
});
})();
- /******************************************************************************/
- /******************************************************************************/
-
// Executed only once.
//
// https://github.com/gorhill/httpswitchboard/issues/25
@@ -427,12 +436,41 @@
// https://github.com/gorhill/uMatrix/issues/924
// Report inline styles.
- (function() {
- if (
- document.querySelector('script:not([src])') !== null ||
- document.querySelector('a[href^="javascript:"]') !== null ||
- document.querySelector('[onabort],[onblur],[oncancel],[oncanplay],[oncanplaythrough],[onchange],[onclick],[onclose],[oncontextmenu],[oncuechange],[ondblclick],[ondrag],[ondragend],[ondragenter],[ondragexit],[ondragleave],[ondragover],[ondragstart],[ondrop],[ondurationchange],[onemptied],[onended],[onerror],[onfocus],[oninput],[oninvalid],[onkeydown],[onkeypress],[onkeyup],[onload],[onloadeddata],[onloadedmetadata],[onloadstart],[onmousedown],[onmouseenter],[onmouseleave],[onmousemove],[onmouseout],[onmouseover],[onmouseup],[onwheel],[onpause],[onplay],[onplaying],[onprogress],[onratechange],[onreset],[onresize],[onscroll],[onseeked],[onseeking],[onselect],[onshow],[onstalled],[onsubmit],[onsuspend],[ontimeupdate],[ontoggle],[onvolumechange],[onwaiting],[onafterprint],[onbeforeprint],[onbeforeunload],[onhashchange],[onlanguagechange],[onmessage],[onoffline],[ononline],[onpagehide],[onpageshow],[onrejectionhandled],[onpopstate],[onstorage],[onunhandledrejection],[onunload],[oncopy],[oncut],[onpaste]') !== null
- ) {
+ (function () {
+ if (document.querySelector('script:not([src])') !== null
+ || document.querySelector('a[href^="javascript:"]') !== null
+ || document.querySelector('[onabort],[onblur],[oncancel],'
+ + '[oncanplay],[oncanplaythrough],'
+ + '[onchange],[onclick],[onclose],'
+ + '[oncontextmenu],[oncuechange],'
+ + '[ondblclick],[ondrag],[ondragend],'
+ + '[ondragenter],[ondragexit],'
+ + '[ondragleave],[ondragover],'
+ + '[ondragstart],[ondrop],'
+ + '[ondurationchange],[onemptied],'
+ + '[onended],[onerror],[onfocus],'
+ + '[oninput],[oninvalid],[onkeydown],'
+ + '[onkeypress],[onkeyup],[onload],'
+ + '[onloadeddata],[onloadedmetadata],'
+ + '[onloadstart],[onmousedown],'
+ + '[onmouseenter],[onmouseleave],'
+ + '[onmousemove],[onmouseout],'
+ + '[onmouseover],[onmouseup],[onwheel],'
+ + '[onpause],[onplay],[onplaying],'
+ + '[onprogress],[onratechange],[onreset],'
+ + '[onresize],[onscroll],[onseeked],'
+ + '[onseeking],[onselect],[onshow],'
+ + '[onstalled],[onsubmit],[onsuspend],'
+ + '[ontimeupdate],[ontoggle],'
+ + '[onvolumechange],[onwaiting],'
+ + '[onafterprint],[onbeforeprint],'
+ + '[onbeforeunload],[onhashchange],'
+ + '[onlanguagechange],[onmessage],'
+ + '[onoffline],[ononline],[onpagehide],'
+ + '[onpageshow],[onrejectionhandled],'
+ + '[onpopstate],[onstorage],'
+ + '[onunhandledrejection],[onunload],'
+ + '[oncopy],[oncut],[onpaste]') !== null) {
vAPI.messaging.send('contentscript.js', {
what: 'securityPolicyViolation',
directive: 'script-src',
@@ -440,7 +478,7 @@
});
}
- if ( document.querySelector('style,[style]') !== null ) {
+ if (document.querySelector('style,[style]') !== null) {
vAPI.messaging.send('contentscript.js', {
what: 'securityPolicyViolation',
directive: 'style-src',
@@ -453,90 +491,93 @@
collapser.process();
})();
- /******************************************************************************/
- /******************************************************************************/
-
// Executed only once.
-
// https://github.com/gorhill/uMatrix/issues/232
- // Force `display` property, Firefox is still affected by the issue.
-
- (function() {
- var noscripts = document.querySelectorAll('noscript');
- if ( noscripts.length === 0 ) { return; }
-
- var redirectTimer,
- reMetaContent = /^\s*(\d+)\s*;\s*url=(['"]?)([^'"]+)\2/i,
- reSafeURL = /^https?:\/\//;
-
- var autoRefresh = function(root) {
- var meta = root.querySelector('meta[http-equiv="refresh"][content]');
- if ( meta === null ) { return; }
- var match = reMetaContent.exec(meta.getAttribute('content'));
- if ( match === null || match[3].trim() === '' ) { return; }
- var url = new URL(match[3], document.baseURI);
- if ( reSafeURL.test(url.href) === false ) { return; }
- redirectTimer = setTimeout(
- function() {
- location.assign(url.href);
- },
- parseInt(match[1], 10) * 1000 + 1
- );
+ // Force `display` property, Firefox is still affected by the issue.
+
+ (function () {
+ let noscripts = document.querySelectorAll('noscript');
+ if (noscripts.length === 0) {
+ return;
+ }
+
+ let redirectTimer;
+ let reMetaContent = /^\s*(\d+)\s*;\s*url=(['"]?)([^'"]+)\2/i;
+ let reSafeURL = /^https?:\/\//;
+
+ let autoRefresh = function (root) {
+ let meta =
+ root.querySelector('meta[http-equiv="refresh"][content]');
+ if (meta === null) {
+ return;
+ }
+
+ let match = reMetaContent.exec(meta.getAttribute('content'));
+ if (match === null || match[3].trim() === '') {
+ return;
+ }
+
+ let url = new URL(match[3], document.baseURI);
+ if (reSafeURL.test(url.href) === false) {
+ return;
+ }
+
+ redirectTimer = setTimeout(function () {
+ location.assign(url.href);
+ }, parseInt(match[1], 10) * 1000 + 1);
+
meta.parentNode.removeChild(meta);
};
- var morphNoscript = function(from) {
- if ( /^application\/(?:xhtml\+)?xml/.test(document.contentType) ) {
- var to = document.createElement('span');
- while ( from.firstChild !== null ) {
+ let morphNoscript = function (from) {
+ if (/^application\/(?:xhtml\+)?xml/.test(document.contentType)) {
+ let to = document.createElement('span');
+ while (from.firstChild !== null) {
to.appendChild(from.firstChild);
}
return to;
}
- var parser = new DOMParser();
- var doc = parser.parseFromString(
- '<span>' + from.textContent + '</span>',
- 'text/html'
- );
+
+ let parser = new DOMParser();
+ let doc =
+ parser.parseFromString('<span>' + from.textContent + '</span>',
+ 'text/html');
+
return document.adoptNode(doc.querySelector('span'));
};
- var renderNoscriptTags = function(response) {
- if ( response !== true ) { return; }
- var parent, span;
- for ( var noscript of noscripts ) {
- parent = noscript.parentNode;
- if ( parent === null ) { continue; }
- span = morphNoscript(noscript);
+ let renderNoscriptTags = function (response) {
+ if (response !== true) {
+ return;
+ }
+
+ for (let noscript of noscripts) {
+ let parent = noscript.parentNode;
+ if (parent === null) {
+ continue;
+ }
+
+ let span = morphNoscript(noscript);
span.style.setProperty('display', 'inline', 'important');
- if ( redirectTimer === undefined ) {
+
+ if (redirectTimer === undefined) {
autoRefresh(span);
}
+
parent.replaceChild(span, noscript);
}
};
- vAPI.messaging.send(
- 'contentscript.js',
- { what: 'mustRenderNoscriptTags?' },
- renderNoscriptTags
- );
+ vAPI.messaging.send('contentscript.js', {
+ what: 'mustRenderNoscriptTags?'
+ }, renderNoscriptTags);
})();
- /******************************************************************************/
- /******************************************************************************/
-
- vAPI.messaging.send(
- 'contentscript.js',
- { what: 'shutdown?' },
- function(response) {
- if ( response === true ) {
- vAPI.shutdown.exec();
- }
+ vAPI.messaging.send('contentscript.js', {
+ what: 'shutdown?'
+ }, function (response) {
+ if (response === true) {
+ vAPI.shutdown.exec();
}
- );
-
- /******************************************************************************/
- /******************************************************************************/
-
+ });
})();
diff --git a/js/cookies.js b/js/cookies.js
index ee271ca..2e15e03 100644
--- a/js/cookies.js
+++ b/js/cookies.js
@@ -28,181 +28,43 @@
"use strict";
-/******************************************************************************/
-
// Isolate from global namespace
// Use cached-context approach rather than object-based approach, as details
// of the implementation do not need to be visible
-ηMatrix.cookieHunter = (function() {
-
- /******************************************************************************/
-
- var ηm = ηMatrix;
+ηMatrix.cookieHunter = (function () {
+ Cu.import('chrome://ematrix/content/lib/UriTools.jsm');
+ Cu.import('chrome://ematrix/content/lib/CookieCache.jsm');
- var recordPageCookiesQueue = new Map();
- var removePageCookiesQueue = new Map();
- var removeCookieQueue = new Set();
- var cookieDict = new Map();
- var cookieEntryJunkyard = [];
- var processRemoveQueuePeriod = 2 * 60 * 1000;
- var processCleanPeriod = 10 * 60 * 1000;
- var processPageRecordQueueTimer = null;
- var processPageRemoveQueueTimer = null;
-
- /******************************************************************************/
-
- var CookieEntry = function(cookie) {
- this.usedOn = new Set();
- this.init(cookie);
- };
-
- CookieEntry.prototype.init = function(cookie) {
- this.secure = cookie.secure;
- this.session = cookie.session;
- this.anySubdomain = cookie.domain.charAt(0) === '.';
- this.hostname = this.anySubdomain ? cookie.domain.slice(1) : cookie.domain;
- this.domain = ηm.URI.domainFromHostname(this.hostname) || this.hostname;
- this.path = cookie.path;
- this.name = cookie.name;
- this.value = cookie.value;
- this.tstamp = Date.now();
- this.usedOn.clear();
- return this;
- };
-
- // Release anything which may consume too much memory
-
- CookieEntry.prototype.dispose = function() {
- this.hostname = '';
- this.domain = '';
- this.path = '';
- this.name = '';
- this.value = '';
- this.usedOn.clear();
- return this;
- };
-
- /******************************************************************************/
-
- var addCookieToDict = function(cookie) {
- var cookieKey = cookieKeyFromCookie(cookie),
- cookieEntry = cookieDict.get(cookieKey);
- if ( cookieEntry === undefined ) {
- cookieEntry = cookieEntryJunkyard.pop();
- if ( cookieEntry ) {
- cookieEntry.init(cookie);
- } else {
- cookieEntry = new CookieEntry(cookie);
- }
- cookieDict.set(cookieKey, cookieEntry);
- }
- return cookieEntry;
- };
-
- /******************************************************************************/
-
- var addCookiesToDict = function(cookies) {
- var i = cookies.length;
- while ( i-- ) {
- addCookieToDict(cookies[i]);
- }
- };
+ let ηm = ηMatrix;
- /******************************************************************************/
-
- var removeCookieFromDict = function(cookieKey) {
- var cookieEntry = cookieDict.get(cookieKey);
- if ( cookieEntry === undefined ) { return false; }
- cookieDict.delete(cookieKey);
- if ( cookieEntryJunkyard.length < 25 ) {
- cookieEntryJunkyard.push(cookieEntry.dispose());
- }
- return true;
- };
-
- /******************************************************************************/
-
- var cookieKeyBuilder = [
- '', // 0 = scheme
- '://',
- '', // 2 = domain
- '', // 3 = path
- '{',
- '', // 5 = persistent or session
- '-cookie:',
- '', // 7 = name
- '}'
- ];
-
- var cookieKeyFromCookie = function(cookie) {
- var cb = cookieKeyBuilder;
- cb[0] = cookie.secure ? 'https' : 'http';
- cb[2] = cookie.domain.charAt(0) === '.' ? cookie.domain.slice(1) : cookie.domain;
- cb[3] = cookie.path;
- cb[5] = cookie.session ? 'session' : 'persistent';
- cb[7] = cookie.name;
- return cb.join('');
- };
-
- var cookieKeyFromCookieURL = function(url, type, name) {
- var ηmuri = ηm.URI.set(url);
- var cb = cookieKeyBuilder;
- cb[0] = ηmuri.scheme;
- cb[2] = ηmuri.hostname;
- cb[3] = ηmuri.path;
- cb[5] = type;
- cb[7] = name;
- return cb.join('');
- };
-
- /******************************************************************************/
-
- var cookieURLFromCookieEntry = function(entry) {
- if ( !entry ) {
- return '';
- }
- return (entry.secure ? 'https://' : 'http://') + entry.hostname + entry.path;
- };
-
- /******************************************************************************/
-
- var cookieMatchDomains = function(cookieKey, allHostnamesString) {
- var cookieEntry = cookieDict.get(cookieKey);
- if ( cookieEntry === undefined ) { return false; }
- if ( allHostnamesString.indexOf(' ' + cookieEntry.hostname + ' ') < 0 ) {
- if ( !cookieEntry.anySubdomain ) {
- return false;
- }
- if ( allHostnamesString.indexOf('.' + cookieEntry.hostname + ' ') < 0 ) {
- return false;
- }
- }
- return true;
- };
-
- /******************************************************************************/
+ let recordPageCookiesQueue = new Map();
+ let removePageCookiesQueue = new Map();
+ let removeCookieQueue = new Set();
+ let processRemoveQueuePeriod = 2 * 60 * 1000;
+ let processCleanPeriod = 10 * 60 * 1000;
+ let processPageRecordQueueTimer = null;
+ let processPageRemoveQueueTimer = null;
// Look for cookies to record for a specific web page
- var recordPageCookiesAsync = function(pageStats) {
+ let recordPageCookiesAsync = function (pageStats) {
// Store the page stats objects so that it doesn't go away
// before we handle the job.
// rhill 2013-10-19: pageStats could be nil, for example, this can
// happens if a file:// ... makes an xmlHttpRequest
- if ( !pageStats ) {
+ if (!pageStats) {
return;
}
recordPageCookiesQueue.set(pageStats.pageUrl, pageStats);
- if ( processPageRecordQueueTimer === null ) {
- processPageRecordQueueTimer = vAPI.setTimeout(processPageRecordQueue, 1000);
+ if (processPageRecordQueueTimer === null) {
+ processPageRecordQueueTimer =
+ vAPI.setTimeout(processPageRecordQueue, 1000);
}
};
- /******************************************************************************/
-
- var cookieLogEntryBuilder = [
+ let cookieLogEntryBuilder = [
'',
'{',
'',
@@ -211,168 +73,176 @@
'}'
];
- var recordPageCookie = function(pageStore, cookieKey) {
- if ( vAPI.isBehindTheSceneTabId(pageStore.tabId) ) { return; }
+ let recordPageCookie = function (pageStore, key) {
+ if (vAPI.isBehindTheSceneTabId(pageStore.tabId)) {
+ return;
+ }
- var cookieEntry = cookieDict.get(cookieKey);
- var pageHostname = pageStore.pageHostname;
- var block = ηm.mustBlock(pageHostname, cookieEntry.hostname, 'cookie');
+ let entry = CookieCache.get(key);
+ let pageHostname = pageStore.pageHostname;
+ let block = ηm.mustBlock(pageHostname, entry.hostname, 'cookie');
- cookieLogEntryBuilder[0] = cookieURLFromCookieEntry(cookieEntry);
- cookieLogEntryBuilder[2] = cookieEntry.session ? 'session' : 'persistent';
- cookieLogEntryBuilder[4] = encodeURIComponent(cookieEntry.name);
+ cookieLogEntryBuilder[0] = CookieUtils.urlFromEntry(entry);
+ cookieLogEntryBuilder[2] = entry.session ? 'session' : 'persistent';
+ cookieLogEntryBuilder[4] = encodeURIComponent(entry.name);
- var cookieURL = cookieLogEntryBuilder.join('');
+ let cookieURL = cookieLogEntryBuilder.join('');
// rhill 2013-11-20:
// https://github.com/gorhill/httpswitchboard/issues/60
// Need to URL-encode cookie name
pageStore.recordRequest('cookie', cookieURL, block);
- ηm.logger.writeOne(pageStore.tabId, 'net', pageHostname, cookieURL, 'cookie', block);
+ ηm.logger.writeOne(pageStore.tabId, 'net',
+ pageHostname, cookieURL, 'cookie', block);
- cookieEntry.usedOn.add(pageHostname);
+ entry.usedOn.add(pageHostname);
// rhill 2013-11-21:
// https://github.com/gorhill/httpswitchboard/issues/65
// Leave alone cookies from behind-the-scene requests if
// behind-the-scene processing is disabled.
- if ( !block ) {
+ if (!block) {
return;
}
- if ( !ηm.userSettings.deleteCookies ) {
+ if (!ηm.userSettings.deleteCookies) {
return;
}
- removeCookieAsync(cookieKey);
+ removeCookieAsync(key);
};
- /******************************************************************************/
-
// Look for cookies to potentially remove for a specific web page
- var removePageCookiesAsync = function(pageStats) {
+ let removePageCookiesAsync = function (pageStats) {
// Hold onto pageStats objects so that it doesn't go away
// before we handle the job.
// rhill 2013-10-19: pageStats could be nil, for example, this can
// happens if a file:// ... makes an xmlHttpRequest
- if ( !pageStats ) {
+ if (!pageStats) {
return;
}
removePageCookiesQueue.set(pageStats.pageUrl, pageStats);
- if ( processPageRemoveQueueTimer === null ) {
- processPageRemoveQueueTimer = vAPI.setTimeout(processPageRemoveQueue, 15 * 1000);
+ if (processPageRemoveQueueTimer === null) {
+ processPageRemoveQueueTimer =
+ vAPI.setTimeout(processPageRemoveQueue, 15 * 1000);
}
};
- /******************************************************************************/
-
// Candidate for removal
- var removeCookieAsync = function(cookieKey) {
- removeCookieQueue.add(cookieKey);
+ let removeCookieAsync = function (key) {
+ removeCookieQueue.add(key);
};
- /******************************************************************************/
-
- var chromeCookieRemove = function(cookieEntry, name) {
- var url = cookieURLFromCookieEntry(cookieEntry);
- if ( url === '' ) {
+ let chromeCookieRemove = function (entry, name) {
+ let url = CookieUtils.urlFromEntry(entry);
+ if (url === '') {
return;
}
- var sessionCookieKey = cookieKeyFromCookieURL(url, 'session', name);
- var persistCookieKey = cookieKeyFromCookieURL(url, 'persistent', name);
- var callback = function(details) {
- var success = !!details;
- var template = success ? i18nCookieDeleteSuccess : i18nCookieDeleteFailure;
- if ( removeCookieFromDict(sessionCookieKey) ) {
- if ( success ) {
+ let sessionKey = CookieUtils.keyFromURL(UriTools.set(url),
+ 'session', name);
+ let persistKey = CookieUtils.keyFromURL(UriTools.set(url),
+ 'persistent', name);
+
+ let callback = function(details) {
+ let success = !!details;
+ let template = success ?
+ i18nCookieDeleteSuccess :
+ i18nCookieDeleteFailure;
+
+ if (CookieCache.remove(sessionKey)) {
+ if (success) {
ηm.cookieRemovedCounter += 1;
}
- ηm.logger.writeOne('', 'info', 'cookie', template.replace('{{value}}', sessionCookieKey));
+ ηm.logger.writeOne('', 'info', 'cookie',
+ template.replace('{{value}}',
+ sessionKey));
}
- if ( removeCookieFromDict(persistCookieKey) ) {
- if ( success ) {
+ if (CookieCache.remove(persistKey)) {
+ if (success) {
ηm.cookieRemovedCounter += 1;
}
- ηm.logger.writeOne('', 'info', 'cookie', template.replace('{{value}}', persistCookieKey));
+ ηm.logger.writeOne('', 'info', 'cookie',
+ template.replace('{{value}}',
+ persistKey));
}
};
- vAPI.cookies.remove({ url: url, name: name }, callback);
+ vAPI.cookies.remove({
+ url: url, name: name
+ }, callback);
};
- var i18nCookieDeleteSuccess = vAPI.i18n('loggerEntryCookieDeleted');
- var i18nCookieDeleteFailure = vAPI.i18n('loggerEntryDeleteCookieError');
-
- /******************************************************************************/
+ let i18nCookieDeleteSuccess = vAPI.i18n('loggerEntryCookieDeleted');
+ let i18nCookieDeleteFailure = vAPI.i18n('loggerEntryDeleteCookieError');
- var processPageRecordQueue = function() {
+ let processPageRecordQueue = function () {
processPageRecordQueueTimer = null;
- for ( var pageStore of recordPageCookiesQueue.values() ) {
+ for (let pageStore of recordPageCookiesQueue.values()) {
findAndRecordPageCookies(pageStore);
}
recordPageCookiesQueue.clear();
};
- /******************************************************************************/
-
- var processPageRemoveQueue = function() {
+ let processPageRemoveQueue = function () {
processPageRemoveQueueTimer = null;
- for ( var pageStore of removePageCookiesQueue.values() ) {
+ for (let pageStore of removePageCookiesQueue.values()) {
findAndRemovePageCookies(pageStore);
}
removePageCookiesQueue.clear();
};
- /******************************************************************************/
-
// Effectively remove cookies.
- var processRemoveQueue = function() {
- var userSettings = ηm.userSettings;
- var deleteCookies = userSettings.deleteCookies;
+ let processRemoveQueue = function () {
+ let userSettings = ηm.userSettings;
+ let deleteCookies = userSettings.deleteCookies;
// Session cookies which timestamp is *after* tstampObsolete will
// be left untouched
// https://github.com/gorhill/httpswitchboard/issues/257
- var tstampObsolete = userSettings.deleteUnusedSessionCookies ?
- Date.now() - userSettings.deleteUnusedSessionCookiesAfter * 60 * 1000 :
+ let dusc = userSettings.deleteUnusedSessionCookies;
+ let dusca = userSettings.deleteUnusedSessionCookiesAfter;
+ let tstampObsolete = dusc ?
+ Date.now() - dusca * 60 * 1000 :
0;
- var srcHostnames;
- var cookieEntry;
+ let srcHostnames;
+ let entry;
- for ( var cookieKey of removeCookieQueue ) {
+ for (let key of removeCookieQueue) {
// rhill 2014-05-12: Apparently this can happen. I have to
// investigate how (A session cookie has same name as a
// persistent cookie?)
- cookieEntry = cookieDict.get(cookieKey);
- if ( cookieEntry === undefined ) { continue; }
+ entry = CookieCache.get(key);
+ if (entry === undefined) {
+ continue;
+ }
// Delete obsolete session cookies: enabled.
- if ( tstampObsolete !== 0 && cookieEntry.session ) {
- if ( cookieEntry.tstamp < tstampObsolete ) {
- chromeCookieRemove(cookieEntry, cookieEntry.name);
+ if (tstampObsolete !== 0 && entry.session) {
+ if (entry.tstamp < tstampObsolete) {
+ chromeCookieRemove(entry, entry.name);
continue;
}
}
// Delete all blocked cookies: disabled.
- if ( deleteCookies === false ) {
+ if (deleteCookies === false) {
continue;
}
// Query scopes only if we are going to use them
- if ( srcHostnames === undefined ) {
+ if (srcHostnames === undefined) {
srcHostnames = ηm.tMatrix.extractAllSourceHostnames();
}
// Ensure cookie is not allowed on ALL current web pages: It can
// happen that a cookie is blacklisted on one web page while
// being whitelisted on another (because of per-page permissions).
- if ( canRemoveCookie(cookieKey, srcHostnames) ) {
- chromeCookieRemove(cookieEntry, cookieEntry.name);
+ if (canRemoveCookie(key, srcHostnames)) {
+ chromeCookieRemove(entry, entry.name);
}
}
@@ -381,21 +251,21 @@
vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod);
};
- /******************************************************************************/
-
// Once in a while, we go ahead and clean everything that might have been
// left behind.
// Remove only some of the cookies which are candidate for removal: who knows,
// maybe a user has 1000s of cookies sitting in his browser...
- var processClean = function() {
- var us = ηm.userSettings;
- if ( us.deleteCookies || us.deleteUnusedSessionCookies ) {
- var cookieKeys = Array.from(cookieDict.keys()),
- len = cookieKeys.length,
- step, offset, n;
- if ( len > 25 ) {
+ let processClean = function () {
+ let us = ηm.userSettings;
+
+ if (us.deleteCookies || us.deleteUnusedSessionCookies) {
+ let keys = Array.from(CookieCache.keys());
+ let len = keys.length;
+ let step, offset, n;
+
+ if (len > 25) {
step = len / 25;
offset = Math.floor(Math.random() * len);
n = 25;
@@ -404,9 +274,10 @@
offset = 0;
n = len;
}
- var i = offset;
- while ( n-- ) {
- removeCookieAsync(cookieKeys[Math.floor(i % len)]);
+
+ let i = offset;
+ while (n--) {
+ removeCookieAsync(keys[Math.floor(i % len)]);
i += step;
}
}
@@ -414,57 +285,56 @@
vAPI.setTimeout(processClean, processCleanPeriod);
};
- /******************************************************************************/
-
- var findAndRecordPageCookies = function(pageStore) {
- for ( var cookieKey of cookieDict.keys() ) {
- if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) {
- recordPageCookie(pageStore, cookieKey);
+ let findAndRecordPageCookies = function (pageStore) {
+ for (let key of CookieCache.keys()) {
+ if (CookieUtils.matchDomains(key, pageStore.allHostnamesString)) {
+ recordPageCookie(pageStore, key);
}
}
};
- /******************************************************************************/
-
- var findAndRemovePageCookies = function(pageStore) {
- for ( var cookieKey of cookieDict.keys() ) {
- if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) {
- removeCookieAsync(cookieKey);
+ let findAndRemovePageCookies = function (pageStore) {
+ for (let key of CookieCache.keys()) {
+ if (CookieUtils.matchDomains(key, pageStore.allHostnamesString)) {
+ removeCookieAsync(key);
}
}
};
- /******************************************************************************/
-
- var canRemoveCookie = function(cookieKey, srcHostnames) {
- var cookieEntry = cookieDict.get(cookieKey);
- if ( cookieEntry === undefined ) { return false; }
+ let canRemoveCookie = function (key, srcHostnames) {
+ let entry = CookieCache.get(key);
+ if (entry === undefined) {
+ return false;
+ }
- var cookieHostname = cookieEntry.hostname;
- var srcHostname;
+ let cookieHostname = entry.hostname;
+ let srcHostname;
- for ( srcHostname of cookieEntry.usedOn ) {
- if ( ηm.mustAllow(srcHostname, cookieHostname, 'cookie') ) {
+ for (srcHostname of entry.usedOn) {
+ if (ηm.mustAllow(srcHostname, cookieHostname, 'cookie')) {
return false;
}
}
+
// Maybe there is a scope in which the cookie is 1st-party-allowed.
// For example, if I am logged in into `github.com`, I do not want to be
// logged out just because I did not yet open a `github.com` page after
// re-starting the browser.
srcHostname = cookieHostname;
- var pos;
+
+ let pos;
+
for (;;) {
- if ( srcHostnames.has(srcHostname) ) {
- if ( ηm.mustAllow(srcHostname, cookieHostname, 'cookie') ) {
+ if (srcHostnames.has(srcHostname)) {
+ if (ηm.mustAllow(srcHostname, cookieHostname, 'cookie')) {
return false;
}
}
- if ( srcHostname === cookieEntry.domain ) {
+ if (srcHostname === entry.domain) {
break;
}
pos = srcHostname.indexOf('.');
- if ( pos === -1 ) {
+ if (pos === -1) {
break;
}
srcHostname = srcHostname.slice(pos + 1);
@@ -472,81 +342,73 @@
return true;
};
- /******************************************************************************/
-
// Listen to any change in cookieland, we will update page stats accordingly.
- vAPI.cookies.onChanged = function(cookie) {
+ vAPI.cookies.onChanged = function (cookie) {
// rhill 2013-12-11: If cookie value didn't change, no need to record.
// https://github.com/gorhill/httpswitchboard/issues/79
- var cookieKey = cookieKeyFromCookie(cookie);
- var cookieEntry = cookieDict.get(cookieKey);
- if ( cookieEntry === undefined ) {
- cookieEntry = addCookieToDict(cookie);
+ let key = CookieUtils.keyFromCookie(cookie);
+ let entry = CookieCache.get(key);
+
+ if (entry === undefined) {
+ entry = CookieCache.add(cookie);
} else {
- cookieEntry.tstamp = Date.now();
- if ( cookie.value === cookieEntry.value ) { return; }
- cookieEntry.value = cookie.value;
+ entry.tstamp = Date.now();
+ if (cookie.value === entry.value) {
+ return;
+ }
+ entry.value = cookie.value;
}
// Go through all pages and update if needed, as one cookie can be used
// by many web pages, so they need to be recorded for all these pages.
- var pageStores = ηm.pageStores;
- var pageStore;
- for ( var tabId in pageStores ) {
- if ( pageStores.hasOwnProperty(tabId) === false ) {
+ let pageStores = ηm.pageStores;
+ let pageStore;
+ for (let tabId in pageStores) {
+ if (pageStores.hasOwnProperty(tabId) === false) {
continue;
}
pageStore = pageStores[tabId];
- if ( !cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) {
+ if (!CookieUtils.matchDomains(key, pageStore.allHostnamesString)) {
continue;
}
- recordPageCookie(pageStore, cookieKey);
+ recordPageCookie(pageStore, key);
}
};
- /******************************************************************************/
-
// Listen to any change in cookieland, we will update page stats accordingly.
- vAPI.cookies.onRemoved = function(cookie) {
- var cookieKey = cookieKeyFromCookie(cookie);
- if ( removeCookieFromDict(cookieKey) ) {
- ηm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey));
+ vAPI.cookies.onRemoved = function (cookie) {
+ let key = CookieUtils.keyFromCookie(cookie);
+ if (CookieCache.remove(key)) {
+ ηm.logger.writeOne('', 'info', 'cookie',
+ i18nCookieDeleteSuccess.replace('{{value}}',
+ key));
}
};
- /******************************************************************************/
-
// Listen to any change in cookieland, we will update page stats accordingly.
- vAPI.cookies.onAllRemoved = function() {
- for ( var cookieKey of cookieDict.keys() ) {
- if ( removeCookieFromDict(cookieKey) ) {
- ηm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey));
+ vAPI.cookies.onAllRemoved = function () {
+ for (let key of CookieCache.keys()) {
+ if (CookieCache.remove(key)) {
+ ηm.logger.writeOne('', 'info', 'cookie',
+ i18nCookieDeleteSuccess.replace('{{value}}',
+ key));
}
}
};
- /******************************************************************************/
-
- vAPI.cookies.getAll(addCookiesToDict);
+ vAPI.cookies.getAll(CookieCache.addVector);
vAPI.cookies.start();
vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod);
vAPI.setTimeout(processClean, processCleanPeriod);
- /******************************************************************************/
-
// Expose only what is necessary
return {
recordPageCookies: recordPageCookiesAsync,
removePageCookies: removePageCookiesAsync
};
-
- /******************************************************************************/
-
})();
-
-/******************************************************************************/
diff --git a/js/dashboard-common.js b/js/dashboard-common.js
index 68ba7d5..9eba87c 100644
--- a/js/dashboard-common.js
+++ b/js/dashboard-common.js
@@ -23,22 +23,14 @@
'use strict';
-/******************************************************************************/
-
-uDom.onLoad(function() {
-
- /******************************************************************************/
-
+uDom.onLoad(function () {
// Open links in the proper window
uDom('a').attr('target', '_blank');
uDom('a[href*="dashboard.html"]').attr('target', '_parent');
- uDom('.whatisthis').on('click', function() {
- uDom(this).parent()
+ uDom('.whatisthis').on('click', function () {
+ uDom(this)
+ .parent()
.descendants('.whatisthis-expandable')
.toggleClass('whatisthis-expanded');
});
-
-
- /******************************************************************************/
-
});
diff --git a/js/dashboard.js b/js/dashboard.js
index 5818d5c..196d900 100644
--- a/js/dashboard.js
+++ b/js/dashboard.js
@@ -21,37 +21,29 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global uDom */
-
'use strict';
-/******************************************************************************/
-
(function() {
-
- var loadDashboardPanel = function(hash) {
+ let loadDashboardPanel = function (hash) {
var button = uDom(hash);
var url = button.attr('data-dashboard-panel-url');
uDom('iframe').attr('src', url);
- uDom('.tabButton').forEach(function(button){
- button.toggleClass(
- 'selected',
- button.attr('data-dashboard-panel-url') === url
- );
+ uDom('.tabButton').forEach(function (button) {
+ button.toggleClass('selected',
+ button.attr('data-dashboard-panel-url') === url);
});
};
- var onTabClickHandler = function() {
+ let onTabClickHandler = function () {
loadDashboardPanel(window.location.hash);
};
- uDom.onLoad(function() {
+ uDom.onLoad(function () {
window.addEventListener('hashchange', onTabClickHandler);
- var hash = window.location.hash;
- if ( hash.length < 2 ) {
+ let hash = window.location.hash;
+ if (hash.length < 2) {
hash = '#settings';
}
loadDashboardPanel(hash);
});
-
})();
diff --git a/js/hosts-files.js b/js/hosts-files.js
index 8c65648..ba57bde 100644
--- a/js/hosts-files.js
+++ b/js/hosts-files.js
@@ -21,25 +21,16 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global uDom */
-
'use strict';
-/******************************************************************************/
-
-(function() {
-
- /******************************************************************************/
-
- var listDetails = {},
- lastUpdateTemplateString = vAPI.i18n('hostsFilesLastUpdate'),
- hostsFilesSettingsHash,
- reValidExternalList = /[a-z-]+:\/\/\S*\/\S+/;
+(function () {
+ let listDetails = {};
+ let lastUpdateTemplateString = vAPI.i18n('hostsFilesLastUpdate');
+ let hostsFilesSettingsHash;
+ let reValidExternalList = /[a-z-]+:\/\/\S*\/\S+/;
- /******************************************************************************/
-
- vAPI.messaging.addListener(function onMessage(msg) {
- switch ( msg.what ) {
+ vAPI.messaging.addListener(function (msg) {
+ switch (msg.what) {
case 'assetUpdated':
updateAssetStatus(msg);
break;
@@ -54,44 +45,51 @@
}
});
- /******************************************************************************/
-
- var renderNumber = function(value) {
+ let renderNumber = function (value) {
return value.toLocaleString();
};
- /******************************************************************************/
-
- var renderHostsFiles = function(soft) {
- var listEntryTemplate = uDom('#templates .listEntry'),
- listStatsTemplate = vAPI.i18n('hostsFilesPerFileStats'),
- renderElapsedTimeToString = vAPI.i18n.renderElapsedTimeToString,
- reExternalHostFile = /^https?:/;
+ let renderHostsFiles = function (soft) {
+ let listEntryTemplate = uDom('#templates .listEntry');
+ let listStatsTemplate = vAPI.i18n('hostsFilesPerFileStats');
+ let renderETTS = vAPI.i18n.renderElapsedTimeToString;
+ let reExternalHostFile = /^https?:/;
// Assemble a pretty list name if possible
- var listNameFromListKey = function(listKey) {
- var list = listDetails.current[listKey] || listDetails.available[listKey];
- var listTitle = list ? list.title : '';
- if ( listTitle === '' ) { return listKey; }
+ let listNameFromListKey = function (listKey) {
+ let list =
+ listDetails.current[listKey] || listDetails.available[listKey];
+ let listTitle = list ? list.title : '';
+
+ if (listTitle === '') {
+ return listKey;
+ }
+
return listTitle;
};
- var liFromListEntry = function(listKey, li) {
- var entry = listDetails.available[listKey],
- elem;
- if ( !li ) {
+ let liFromListEntry = function (listKey, li) {
+ let entry = listDetails.available[listKey];
+ let elem;
+
+ if (!li) {
li = listEntryTemplate.clone().nodeAt(0);
}
- if ( li.getAttribute('data-listkey') !== listKey ) {
+
+ if (li.getAttribute('data-listkey') !== listKey) {
li.setAttribute('data-listkey', listKey);
+
elem = li.querySelector('input[type="checkbox"]');
- elem.checked = entry.off !== true;
+ elem.checked = (entry.off !== true);
elem = li.querySelector('a:nth-of-type(1)');
- elem.setAttribute('href', 'asset-viewer.html?url=' + encodeURI(listKey));
+ elem.setAttribute('href',
+ 'asset-viewer.html?url=' + encodeURI(listKey));
elem.setAttribute('type', 'text/html');
elem.textContent = listNameFromListKey(listKey);
+
li.classList.remove('toRemove');
- if ( entry.supportName ) {
+
+ if (entry.supportName) {
li.classList.add('support');
elem = li.querySelector('a.support');
elem.setAttribute('href', entry.supportURL);
@@ -99,12 +97,14 @@
} else {
li.classList.remove('support');
}
- if ( entry.external ) {
+
+ if (entry.external) {
li.classList.add('external');
} else {
li.classList.remove('external');
}
- if ( entry.instructionURL ) {
+
+ if (entry.instructionURL) {
li.classList.add('mustread');
elem = li.querySelector('a.mustread');
elem.setAttribute('href', entry.instructionURL);
@@ -112,40 +112,51 @@
li.classList.remove('mustread');
}
}
+
// https://github.com/gorhill/uBlock/issues/1429
- if ( !soft ) {
+ if (!soft) {
elem = li.querySelector('input[type="checkbox"]');
elem.checked = entry.off !== true;
}
+
elem = li.querySelector('span.counts');
- var text = '';
- if ( !isNaN(+entry.entryUsedCount) && !isNaN(+entry.entryCount) ) {
+
+ let text = '';
+ if (!isNaN(+entry.entryUsedCount) && !isNaN(+entry.entryCount)) {
text = listStatsTemplate
- .replace('{{used}}', renderNumber(entry.off ? 0 : entry.entryUsedCount))
- .replace('{{total}}', renderNumber(entry.entryCount));
+ .replace('{{used}}',
+ renderNumber(entry.off ? 0 : entry.entryUsedCount))
+ .replace('{{total}}',
+ renderNumber(entry.entryCount));
}
+
elem.textContent = text;
+
// https://github.com/chrisaljoudi/uBlock/issues/104
- var asset = listDetails.cache[listKey] || {};
- var remoteURL = asset.remoteURL;
- li.classList.toggle(
- 'unsecure',
- typeof remoteURL === 'string' && remoteURL.lastIndexOf('http:', 0) === 0
- );
+ let asset = listDetails.cache[listKey] || {};
+ let remoteURL = asset.remoteURL;
+
+ li.classList.toggle('unsecure',
+ typeof remoteURL === 'string'
+ && remoteURL.lastIndexOf('http:', 0) === 0);
li.classList.toggle('failed', asset.error !== undefined);
li.classList.toggle('obsolete', asset.obsolete === true);
- li.classList.toggle('cached', asset.cached === true && asset.writeTime > 0);
- if ( asset.cached ) {
- li.querySelector('.status.cache').setAttribute(
- 'title',
- lastUpdateTemplateString.replace('{{ago}}', renderElapsedTimeToString(asset.writeTime))
- );
+ li.classList.toggle('cached',
+ asset.cached === true && asset.writeTime > 0);
+
+ if (asset.cached) {
+ li.querySelector('.status.cache')
+ .setAttribute('title',
+ lastUpdateTemplateString
+ .replace('{{ago}}',
+ renderETTS(asset.writeTime)));
}
+
li.classList.remove('discard');
return li;
};
- var onListsReceived = function(details) {
+ let onListsReceived = function (details) {
// Before all, set context vars
listDetails = details;
@@ -153,239 +164,239 @@
// DOM list entries.
uDom('#lists .listEntry').addClass('discard');
- var availableLists = details.available,
- listKeys = Object.keys(details.available);
+ let availableLists = details.available;
+ let listKeys = Object.keys(details.available);
// Sort works this way:
// - Send /^https?:/ items at the end (custom hosts file URL)
- listKeys.sort(function(a, b) {
- var ta = availableLists[a].title || a,
- tb = availableLists[b].title || b;
- if ( reExternalHostFile.test(ta) === reExternalHostFile.test(tb) ) {
+ listKeys.sort(function (a, b) {
+ let ta = availableLists[a].title || a;
+ let tb = availableLists[b].title || b;
+
+ if (reExternalHostFile.test(ta) === reExternalHostFile.test(tb)) {
return ta.localeCompare(tb);
}
+
return reExternalHostFile.test(tb) ? -1 : 1;
});
- var ulList = document.querySelector('#lists');
- for ( var i = 0; i < listKeys.length; i++ ) {
- var liEntry = liFromListEntry(listKeys[i], ulList.children[i]);
- if ( liEntry.parentElement === null ) {
+ let ulList = document.querySelector('#lists');
+
+ for (let i=0; i<listKeys.length; ++i) {
+ let liEntry = liFromListEntry(listKeys[i], ulList.children[i]);
+ if (liEntry.parentElement === null) {
ulList.appendChild(liEntry);
}
}
uDom('#lists .listEntry.discard').remove();
- uDom('#listsOfBlockedHostsPrompt').text(
- vAPI.i18n('hostsFilesStats').replace(
- '{{blockedHostnameCount}}',
- renderNumber(details.blockedHostnameCount)
- )
- );
- uDom('#autoUpdate').prop('checked', listDetails.autoUpdate === true);
-
- if ( !soft ) {
+ uDom('#listsOfBlockedHostsPrompt')
+ .text(vAPI.i18n('hostsFilesStats')
+ .replace('{{blockedHostnameCount}}',
+ renderNumber(details.blockedHostnameCount)));
+ uDom('#autoUpdate').prop('checked',
+ listDetails.autoUpdate === true);
+
+ if (!soft) {
hostsFilesSettingsHash = hashFromCurrentFromSettings();
}
+
renderWidgets();
};
- vAPI.messaging.send('hosts-files.js', { what: 'getLists' }, onListsReceived);
+ vAPI.messaging.send('hosts-files.js', {
+ what: 'getLists'
+ }, onListsReceived);
};
- /******************************************************************************/
-
- var renderWidgets = function() {
- uDom('#buttonUpdate').toggleClass('disabled', document.querySelector('body:not(.updating) #lists .listEntry.obsolete > input[type="checkbox"]:checked') === null);
- uDom('#buttonPurgeAll').toggleClass('disabled', document.querySelector('#lists .listEntry.cached') === null);
- uDom('#buttonApply').toggleClass('disabled', hostsFilesSettingsHash === hashFromCurrentFromSettings());
+ let renderWidgets = function () {
+ let sel1 =
+ 'body:not(.updating) #lists .listEntry.obsolete '
+ + '> input[type="checkbox"]:checked';
+ let sel2 = '#lists .listEntry.cached';
+
+ uDom('#buttonUpdate')
+ .toggleClass('disabled', document.querySelector(sel1) === null);
+ uDom('#buttonPurgeAll')
+ .toggleClass('disabled', document.querySelector(sel2) === null);
+ uDom('#buttonApply')
+ .toggleClass('disabled',
+ hostsFilesSettingsHash ===
+ hashFromCurrentFromSettings());
};
- /******************************************************************************/
+ let updateAssetStatus = function (details) {
+ let li = document
+ .querySelector('#lists .listEntry[data-listkey="'+details.key+'"]');
+ if (li === null) {
+ return;
+ }
- var updateAssetStatus = function(details) {
- var li = document.querySelector('#lists .listEntry[data-listkey="' + details.key + '"]');
- if ( li === null ) { return; }
li.classList.toggle('failed', !!details.failed);
li.classList.toggle('obsolete', !details.cached);
li.classList.toggle('cached', !!details.cached);
- if ( details.cached ) {
- li.querySelector('.status.cache').setAttribute(
- 'title',
- lastUpdateTemplateString.replace(
- '{{ago}}',
- vAPI.i18n.renderElapsedTimeToString(Date.now())
- )
- );
+
+ if (details.cached) {
+ let str = vAPI.i18n.renderElapsedTimeToString(Date.now());
+ li.querySelector('.status.cache')
+ .setAttribute('title',
+ lastUpdateTemplateString.replace('{{ago}}', str));
}
+
renderWidgets();
};
- /*******************************************************************************
-
- Compute a hash from all the settings affecting how filter lists are loaded
- in memory.
-
+ /**
+ Compute a hash from all the settings affecting how filter lists are loaded
+ in memory.
**/
-
- var hashFromCurrentFromSettings = function() {
- var hash = [],
- listHash = [],
- listEntries = document.querySelectorAll('#lists .listEntry[data-listkey]:not(.toRemove)'),
- liEntry,
- i = listEntries.length;
- while ( i-- ) {
- liEntry = listEntries[i];
- if ( liEntry.querySelector('input[type="checkbox"]:checked') !== null ) {
- listHash.push(liEntry.getAttribute('data-listkey'));
+ let hashFromCurrentFromSettings = function () {
+ let hash = [];
+ let listHash = [];
+ let sel = '#lists .listEntry[data-listkey]:not(.toRemove)';
+ let ext = 'externalHostsFiles';
+ let listEntries = document.querySelectorAll(sel);
+
+ for (let i=listEntries.length-1; i>=0; --i) {
+ let li = listEntries[i];
+ if (li.querySelector('input[type="checkbox"]:checked') !== null) {
+ listHash.push(li.getAttribute('data-listkey'));
}
}
- hash.push(
- listHash.sort().join(),
- reValidExternalList.test(document.getElementById('externalHostsFiles').value),
- document.querySelector('#lists .listEntry.toRemove') !== null
- );
+
+ hash.push(listHash.sort().join(),
+ reValidExternalList.test(document.getElementById(ext).value),
+ document.querySelector('#lists .listEntry.toRemove') !== null);
+
return hash.join();
};
- /******************************************************************************/
-
- var onHostsFilesSettingsChanged = function() {
+ let onHostsFilesSettingsChanged = function () {
renderWidgets();
};
- /******************************************************************************/
+ let onRemoveExternalHostsFile = function (ev) {
+ let liEntry = uDom(this).ancestors('[data-listkey]');
+ let listKey = liEntry.attr('data-listkey');
- var onRemoveExternalHostsFile = function(ev) {
- var liEntry = uDom(this).ancestors('[data-listkey]'),
- listKey = liEntry.attr('data-listkey');
- if ( listKey ) {
+ if (listKey) {
liEntry.toggleClass('toRemove');
renderWidgets();
}
+
ev.preventDefault();
};
- /******************************************************************************/
+ let onPurgeClicked = function () {
+ let button = uDom(this);
+ let liEntry = button.ancestors('[data-listkey]');
+ let listKey = liEntry.attr('data-listkey');
- var onPurgeClicked = function() {
- var button = uDom(this),
- liEntry = button.ancestors('[data-listkey]'),
- listKey = liEntry.attr('data-listkey');
- if ( !listKey ) { return; }
+ if (!listKey) {
+ return;
+ }
+
+ vAPI.messaging.send('hosts-files.js', {
+ what: 'purgeCache',
+ assetKey: listKey
+ });
- vAPI.messaging.send('hosts-files.js', { what: 'purgeCache', assetKey: listKey });
liEntry.addClass('obsolete');
liEntry.removeClass('cached');
- if ( liEntry.descendants('input').first().prop('checked') ) {
+ if (liEntry.descendants('input').first().prop('checked')) {
renderWidgets();
}
};
- /******************************************************************************/
-
- var selectHostsFiles = function(callback) {
+ let selectHostsFiles = function (callback) {
// Hosts files to select
- var toSelect = [],
- liEntries = document.querySelectorAll('#lists .listEntry[data-listkey]:not(.toRemove)'),
- i = liEntries.length,
- liEntry;
- while ( i-- ) {
- liEntry = liEntries[i];
- if ( liEntry.querySelector('input[type="checkbox"]:checked') !== null ) {
- toSelect.push(liEntry.getAttribute('data-listkey'));
+ let toSelect = [];
+ let sel = '#lists .listEntry[data-listkey]:not(.toRemove)';
+ let sel2 = '#lists .listEntry.toRemove[data-listkey]';
+ let liEntries = document.querySelectorAll(sel);
+
+ for (let i=liEntries.length-1; i>=0; --i) {
+ let li = liEntries[i];
+ if (li.querySelector('input[type="checkbox"]:checked') !== null) {
+ toSelect.push(li.getAttribute('data-listkey'));
}
}
// External hosts files to remove
- var toRemove = [];
- liEntries = document.querySelectorAll('#lists .listEntry.toRemove[data-listkey]');
- i = liEntries.length;
- while ( i-- ) {
+ let toRemove = [];
+ liEntries = document.querySelectorAll(sel2);
+
+ for (let i=liEntries.length-1; i>=0; --i) {
toRemove.push(liEntries[i].getAttribute('data-listkey'));
}
// External hosts files to import
- var externalListsElem = document.getElementById('externalHostsFiles'),
- toImport = externalListsElem.value.trim();
+ let externalListsElem = document.getElementById('externalHostsFiles');
+ let toImport = externalListsElem.value.trim();
+
externalListsElem.value = '';
- vAPI.messaging.send(
- 'hosts-files.js',
- {
- what: 'selectHostsFiles',
- toSelect: toSelect,
- toImport: toImport,
- toRemove: toRemove
- },
- callback
- );
+ vAPI.messaging.send('hosts-files.js', {
+ what: 'selectHostsFiles',
+ toSelect: toSelect,
+ toImport: toImport,
+ toRemove: toRemove
+ }, callback);
hostsFilesSettingsHash = hashFromCurrentFromSettings();
};
- /******************************************************************************/
-
- var buttonApplyHandler = function() {
+ let buttonApplyHandler = function () {
uDom('#buttonApply').removeClass('enabled');
- selectHostsFiles(function() {
- vAPI.messaging.send('hosts-files.js', { what: 'reloadHostsFiles' });
+ selectHostsFiles(function () {
+ vAPI.messaging.send('hosts-files.js', {
+ what: 'reloadHostsFiles'
+ });
});
+
renderWidgets();
};
- /******************************************************************************/
-
- var buttonUpdateHandler = function() {
+ let buttonUpdateHandler = function () {
uDom('#buttonUpdate').removeClass('enabled');
- selectHostsFiles(function() {
+ selectHostsFiles(function () {
document.body.classList.add('updating');
- vAPI.messaging.send('hosts-files.js', { what: 'forceUpdateAssets' });
+ vAPI.messaging.send('hosts-files.js', {
+ what: 'forceUpdateAssets'
+ });
renderWidgets();
});
renderWidgets();
};
- /******************************************************************************/
-
- var buttonPurgeAllHandler = function() {
+ let buttonPurgeAllHandler = function () {
uDom('#buttonPurgeAll').removeClass('enabled');
- vAPI.messaging.send(
- 'hosts-files.js',
- { what: 'purgeAllCaches' },
- function() {
- renderHostsFiles(true);
- }
- );
+ vAPI.messaging.send('hosts-files.js', {
+ what: 'purgeAllCaches'
+ }, function () {
+ renderHostsFiles(true);
+ });
};
- /******************************************************************************/
-
- var autoUpdateCheckboxChanged = function() {
- vAPI.messaging.send(
- 'hosts-files.js',
- {
- what: 'userSettings',
- name: 'autoUpdate',
- value: this.checked
- }
- );
+ let autoUpdateCheckboxChanged = function () {
+ vAPI.messaging.send('hosts-files.js', {
+ what: 'userSettings',
+ name: 'autoUpdate',
+ value: this.checked
+ });
};
- /******************************************************************************/
-
uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged);
uDom('#buttonApply').on('click', buttonApplyHandler);
uDom('#buttonUpdate').on('click', buttonUpdateHandler);
uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler);
- uDom('#lists').on('change', '.listEntry > input', onHostsFilesSettingsChanged);
- uDom('#lists').on('click', '.listEntry > a.remove', onRemoveExternalHostsFile);
+ uDom('#lists').on('change', '.listEntry > input',
+ onHostsFilesSettingsChanged);
+ uDom('#lists').on('click', '.listEntry > a.remove',
+ onRemoveExternalHostsFile);
uDom('#lists').on('click', 'span.cache', onPurgeClicked);
uDom('#externalHostsFiles').on('input', onHostsFilesSettingsChanged);
renderHostsFiles();
-
- /******************************************************************************/
-
})();
diff --git a/js/httpsb.js b/js/httpsb.js
index b235f70..824a302 100644
--- a/js/httpsb.js
+++ b/js/httpsb.js
@@ -28,6 +28,8 @@
/******************************************************************************/
(function() {
+ Cu.import('chrome://ematrix/content/lib/UriTools.jsm');
+
var ηm = ηMatrix;
ηm.pMatrix = new ηm.Matrix();
ηm.pMatrix.setSwitch('matrix-off', 'about-scheme', 1);
@@ -59,7 +61,7 @@
/******************************************************************************/
ηMatrix.hostnameFromURL = function(url) {
- var hn = this.URI.hostnameFromURI(url);
+ var hn = UriTools.hostnameFromURI(url);
return hn === '' ? '*' : hn;
};
@@ -68,7 +70,7 @@
/******************************************************************************/
ηMatrix.evaluateURL = function(srcURL, desHostname, type) {
- var srcHostname = this.URI.hostnameFromURI(srcURL);
+ var srcHostname = UriTools.hostnameFromURI(srcURL);
return this.tMatrix.evaluateCellZXY(srcHostname, desHostname, type);
};
@@ -93,7 +95,7 @@
// done only from within a scope.
ηMatrix.autoWhitelistAllTemporarily = function(pageURL) {
- var srcHostname = this.URI.hostnameFromURI(pageURL);
+ var srcHostname = UriTools.hostnameFromURI(pageURL);
if ( this.mustBlock(srcHostname, '*', '*') === false ) {
return false;
}
diff --git a/js/i18n.js b/js/i18n.js
index 3a6b0e2..7c377bb 100644
--- a/js/i18n.js
+++ b/js/i18n.js
@@ -43,13 +43,15 @@
// used to check the source text. The above comment is kept just
// in case.
- let reSafeTags = /^([\s\S]*?)<(b|blockquote|code|em|i|kbd|span|sup)>(.+?)<\/\2>([\s\S]*)$/;
+ let reSafeTags =
+ /^([\s\S]*?)<(b|blockquote|code|em|i|kbd|span|sup)>(.+?)<\/\2>([\s\S]*)$/;
let reSafeInput = /^([\s\S]*?)<(input type="[^"]+")>(.*?)([\s\S]*)$/;
let reInput = /^input type=(['"])([a-z]+)\1$/;
- let reSafeLink = /^([\s\S]*?)<(a href=['"]https?:\/\/[^'" <>]+['"])>(.+?)<\/a>([\s\S]*)$/;
+ let reSafeLink =
+ /^([\s\S]*?)<(a href=['"]https?:\/\/[^'" <>]+['"])>(.+?)<\/a>([\s\S]*)$/;
let reLink = /^a href=(['"])(https?:\/\/[^'"]+)\1$/;
- var safeTextToTagNode = function(text) {
+ let safeTextToTagNode = function (text) {
let matches;
let node;
@@ -96,7 +98,7 @@
}
};
- var safeTextToTextNode = function(text) {
+ let safeTextToTextNode = function (text) {
if (text.indexOf('&') !== -1) {
text = text
.replace(/&ldquo;/g, '“')
@@ -110,7 +112,7 @@
return document.createTextNode(text);
};
- var safeTextToDOM = function(text, parent) {
+ let safeTextToDOM = function (text, parent) {
if (text === '') {
return;
}
@@ -150,76 +152,74 @@
safeTextToDOM(matches[4], parent);
};
- /******************************************************************************/
-
// Helper to deal with the i18n'ing of HTML files.
- vAPI.i18n.render = function(context) {
- var docu = document,
- root = context || docu,
- elems, n, i, elem, text;
-
- elems = root.querySelectorAll('[data-i18n]');
- n = elems.length;
- for ( i = 0; i < n; i++ ) {
+ vAPI.i18n.render = function (context) {
+ let docu = document;
+ let root = context || docu;
+ let i, elem, text;
+
+ let elems = root.querySelectorAll('[data-i18n]');
+ let n = elems.length;
+ for (i=0; i<n; ++i) {
elem = elems[i];
text = vAPI.i18n(elem.getAttribute('data-i18n'));
- if ( !text ) { continue; }
+ if (!text) {
+ continue;
+ }
// TODO: remove once it's all replaced with <input type="...">
- if ( text.indexOf('{') !== -1 ) {
- text = text.replace(/\{\{input:([^}]+)\}\}/g, '<input type="$1">');
+ if (text.indexOf('{') !== -1) {
+ text =
+ text.replace(/\{\{input:([^}]+)\}\}/g, '<input type="$1">');
}
safeTextToDOM(text, elem);
}
- uDom('[title]', context).forEach(function(elem) {
- var title = vAPI.i18n(elem.attr('title'));
- if ( title ) {
+ uDom('[title]', context).forEach(function (elem) {
+ let title = vAPI.i18n(elem.attr('title'));
+ if (title) {
elem.attr('title', title);
}
});
- uDom('[placeholder]', context).forEach(function(elem) {
+ uDom('[placeholder]', context).forEach(function (elem) {
elem.attr('placeholder', vAPI.i18n(elem.attr('placeholder')));
});
- uDom('[data-i18n-tip]', context).forEach(function(elem) {
- elem.attr(
- 'data-tip',
- vAPI.i18n(elem.attr('data-i18n-tip'))
- .replace(/<br>/g, '\n')
- .replace(/\n{3,}/g, '\n\n')
- );
+ uDom('[data-i18n-tip]', context).forEach(function (elem) {
+ elem.attr('data-tip',
+ vAPI.i18n(elem.attr('data-i18n-tip'))
+ .replace(/<br>/g, '\n')
+ .replace(/\n{3,}/g, '\n\n'));
});
};
vAPI.i18n.render();
- /******************************************************************************/
-
- vAPI.i18n.renderElapsedTimeToString = function(tstamp) {
- var value = (Date.now() - tstamp) / 60000;
- if ( value < 2 ) {
+ vAPI.i18n.renderElapsedTimeToString = function (tstamp) {
+ let value = (Date.now() - tstamp) / 60000;
+ if (value < 2) {
return vAPI.i18n('elapsedOneMinuteAgo');
}
- if ( value < 60 ) {
- return vAPI.i18n('elapsedManyMinutesAgo').replace('{{value}}', Math.floor(value).toLocaleString());
+ if (value < 60) {
+ return vAPI
+ .i18n('elapsedManyMinutesAgo')
+ .replace('{{value}}', Math.floor(value).toLocaleString());
}
value /= 60;
- if ( value < 2 ) {
+ if (value < 2) {
return vAPI.i18n('elapsedOneHourAgo');
}
- if ( value < 24 ) {
- return vAPI.i18n('elapsedManyHoursAgo').replace('{{value}}', Math.floor(value).toLocaleString());
+ if (value < 24) {
+ return vAPI
+ .i18n('elapsedManyHoursAgo')
+ .replace('{{value}}', Math.floor(value).toLocaleString());
}
value /= 24;
- if ( value < 2 ) {
+ if (value < 2) {
return vAPI.i18n('elapsedOneDayAgo');
}
- return vAPI.i18n('elapsedManyDaysAgo').replace('{{value}}', Math.floor(value).toLocaleString());
+ return vAPI
+ .i18n('elapsedManyDaysAgo')
+ .replace('{{value}}', Math.floor(value).toLocaleString());
};
-
- /******************************************************************************/
-
})();
-
-/******************************************************************************/
diff --git a/js/logger-ui.js b/js/logger-ui.js
index 590e67b..aefb733 100644
--- a/js/logger-ui.js
+++ b/js/logger-ui.js
@@ -21,164 +21,157 @@
uMatrix Home: https://github.com/gorhill/sessbench
*/
-/* global uDom */
-
'use strict';
-/******************************************************************************/
-
-(function() {
-
- /******************************************************************************/
-
- var tbody = document.querySelector('#content tbody');
- var trJunkyard = [];
- var tdJunkyard = [];
- var firstVarDataCol = 2; // currently, column 2 (0-based index)
- var lastVarDataIndex = 3; // currently, d0-d3
- var maxEntries = 0;
- var noTabId = '';
- var allTabIds = {};
- var allTabIdsToken;
- var ownerId = Date.now();
-
- var emphasizeTemplate = document.querySelector('#emphasizeTemplate > span');
- var hiddenTemplate = document.querySelector('#hiddenTemplate > span');
-
- var prettyRequestTypes = {
+(function () {
+ let tbody = document.querySelector('#content tbody');
+ let trJunkyard = [];
+ let tdJunkyard = [];
+ let firstVarDataCol = 2; // currently, column 2 (0-based index)
+ let lastVarDataIndex = 3; // currently, d0-d3
+ let maxEntries = 0;
+ let noTabId = '';
+ let allTabIds = {};
+ let allTabIdsToken;
+ let ownerId = Date.now();
+
+ let emphasizeTemplate = document.querySelector('#emphasizeTemplate > span');
+ let hiddenTemplate = document.querySelector('#hiddenTemplate > span');
+
+ let prettyRequestTypes = {
'main_frame': 'doc',
'stylesheet': 'css',
'sub_frame': 'frame',
'xmlhttprequest': 'xhr'
};
- var dontEmphasizeSet = new Set([
+ let dontEmphasizeSet = new Set([
'COOKIE',
'CSP',
'REFERER'
]);
- /******************************************************************************/
-
// Adjust top padding of content table, to match that of toolbar height.
- document.getElementById('content').style.setProperty(
- 'margin-top',
- document.getElementById('toolbar').clientHeight + 'px'
- );
+ document
+ .getElementById('content')
+ .style
+ .setProperty('margin-top',
+ document.getElementById('toolbar').clientHeight + 'px');
- /******************************************************************************/
-
- var classNameFromTabId = function(tabId) {
- if ( tabId === noTabId ) {
+ let classNameFromTabId = function (tabId) {
+ if (tabId === noTabId) {
return 'tab_bts';
}
- if ( tabId !== '' ) {
+ if (tabId !== '') {
return 'tab_' + tabId;
}
return '';
};
- /******************************************************************************/
-
// Emphasize hostname and cookie name.
- var emphasizeCookie = function(s) {
- var pnode = emphasizeHostname(s);
- if ( pnode.childNodes.length !== 3 ) {
+ let emphasizeCookie = function (s) {
+ let pnode = emphasizeHostname(s);
+ if (pnode.childNodes.length !== 3) {
return pnode;
}
- var prefix = '-cookie:';
- var text = pnode.childNodes[2].textContent;
- var beg = text.indexOf(prefix);
- if ( beg === -1 ) {
+
+ let prefix = '-cookie:';
+ let text = pnode.childNodes[2].textContent;
+
+ let beg = text.indexOf(prefix);
+ if (beg === -1) {
return pnode;
}
beg += prefix.length;
- var end = text.indexOf('}', beg);
- if ( end === -1 ) {
+
+ let end = text.indexOf('}', beg);
+ if (end === -1) {
return pnode;
}
- var cnode = emphasizeTemplate.cloneNode(true);
+
+ let cnode = emphasizeTemplate.cloneNode(true);
cnode.childNodes[0].textContent = text.slice(0, beg);
cnode.childNodes[1].textContent = text.slice(beg, end);
cnode.childNodes[2].textContent = text.slice(end);
pnode.replaceChild(cnode.childNodes[0], pnode.childNodes[2]);
pnode.appendChild(cnode.childNodes[0]);
pnode.appendChild(cnode.childNodes[0]);
+
return pnode;
};
- /******************************************************************************/
-
// Emphasize hostname in URL.
- var emphasizeHostname = function(url) {
- var hnbeg = url.indexOf('://');
- if ( hnbeg === -1 ) {
+ let emphasizeHostname = function (url) {
+ let hnbeg = url.indexOf('://');
+ if (hnbeg === -1) {
return document.createTextNode(url);
}
hnbeg += 3;
- var hnend = url.indexOf('/', hnbeg);
- if ( hnend === -1 ) {
+ let hnend = url.indexOf('/', hnbeg);
+ if (hnend === -1) {
hnend = url.slice(hnbeg).search(/\?#/);
- if ( hnend !== -1 ) {
+ if (hnend !== -1) {
hnend += hnbeg;
} else {
hnend = url.length;
}
}
- var node = emphasizeTemplate.cloneNode(true);
+ let node = emphasizeTemplate.cloneNode(true);
node.childNodes[0].textContent = url.slice(0, hnbeg);
node.childNodes[1].textContent = url.slice(hnbeg, hnend);
node.childNodes[2].textContent = url.slice(hnend);
+
return node;
};
- /******************************************************************************/
-
- var createCellAt = function(tr, index) {
- var td = tr.cells[index];
- var mustAppend = !td;
- if ( mustAppend ) {
+ let createCellAt = function (tr, index) {
+ let td = tr.cells[index];
+ let mustAppend = !td;
+ if (mustAppend) {
td = tdJunkyard.pop();
}
- if ( td ) {
+
+ if (td) {
td.removeAttribute('colspan');
td.textContent = '';
} else {
td = document.createElement('td');
}
- if ( mustAppend ) {
+ if (mustAppend) {
tr.appendChild(td);
}
+
return td;
};
- /******************************************************************************/
-
- var createRow = function(layout) {
- var tr = trJunkyard.pop();
- if ( tr ) {
+ let createRow = function (layout) {
+ let tr = trJunkyard.pop();
+ if (tr) {
tr.className = '';
} else {
tr = document.createElement('tr');
}
- for ( var index = 0; index < firstVarDataCol; index++ ) {
+
+ let index;
+ for (index=0; index<firstVarDataCol; ++index) {
createCellAt(tr, index);
}
- var i = 1, span = 1, td;
+
+ let i = 1, span = 1, td;
for (;;) {
td = createCellAt(tr, index);
- if ( i === lastVarDataIndex ) {
+ if (i === lastVarDataIndex) {
break;
}
- if ( layout.charAt(i) !== '1' ) {
+ if (layout.charAt(i) !== '1') {
span += 1;
} else {
- if ( span !== 1 ) {
+ if (span !== 1) {
td.setAttribute('colspan', span);
}
index += 1;
@@ -186,34 +179,30 @@
}
i += 1;
}
- if ( span !== 1 ) {
+
+ if (span !== 1) {
td.setAttribute('colspan', span);
}
index += 1;
- while ( (td = tr.cells[index]) ) {
+ while ((td = tr.cells[index])) {
tdJunkyard.push(tr.removeChild(td));
}
+
return tr;
};
- /******************************************************************************/
-
- var createHiddenTextNode = function(text) {
- var node = hiddenTemplate.cloneNode(true);
+ let createHiddenTextNode = function (text) {
+ let node = hiddenTemplate.cloneNode(true);
node.textContent = text;
return node;
};
- /******************************************************************************/
-
- var padTo2 = function(v) {
+ let padTo2 = function (v) {
return v < 10 ? '0' + v : v;
};
- /******************************************************************************/
-
- var createGap = function(tabId, url) {
- var tr = createRow('1');
+ let createGap = function (tabId, url) {
+ let tr = createRow('1');
tr.classList.add('doc');
tr.classList.add('tab');
tr.classList.add('canMtx');
@@ -222,39 +211,41 @@
tbody.insertBefore(tr, tbody.firstChild);
};
- /******************************************************************************/
-
- var renderLogEntry = function(entry) {
- var tr;
- var fvdc = firstVarDataCol;
+ let renderLogEntry = function (entry) {
+ let tr;
+ let fvdc = firstVarDataCol;
- switch ( entry.cat ) {
+ switch (entry.cat) {
case 'error':
case 'info':
tr = createRow('1');
- if ( entry.d0 === 'cookie' ) {
+ if (entry.d0 === 'cookie') {
tr.cells[fvdc].appendChild(emphasizeCookie(entry.d1));
} else {
tr.cells[fvdc].textContent = entry.d0;
}
break;
-
case 'net':
tr = createRow('111');
tr.classList.add('canMtx');
+
// If the request is that of a root frame, insert a gap in the table
// in order to visually separate entries for different documents.
- if ( entry.d2 === 'doc' && entry.tab !== noTabId ) {
+ if (entry.d2 === 'doc' && entry.tab !== noTabId) {
createGap(entry.tab, entry.d1);
}
- if ( entry.d3 ) {
+
+ if (entry.d3) {
tr.classList.add('blocked');
tr.cells[fvdc].textContent = '--';
} else {
tr.cells[fvdc].textContent = '';
}
- tr.cells[fvdc+1].textContent = (prettyRequestTypes[entry.d2] || entry.d2);
- if ( dontEmphasizeSet.has(entry.d2) ) {
+
+ tr.cells[fvdc+1].textContent =
+ (prettyRequestTypes[entry.d2] || entry.d2);
+
+ if (dontEmphasizeSet.has(entry.d2)) {
tr.cells[fvdc+2].textContent = entry.d1;
} else if ( entry.d2 === 'cookie' ) {
tr.cells[fvdc+2].appendChild(emphasizeCookie(entry.d1));
@@ -262,7 +253,6 @@
tr.cells[fvdc+2].appendChild(emphasizeHostname(entry.d1));
}
break;
-
default:
tr = createRow('1');
tr.cells[fvdc].textContent = entry.d0;
@@ -270,20 +260,22 @@
}
// Fields common to all rows.
- var time = logDate;
+ let time = logDate;
time.setTime(entry.tstamp - logDateTimezoneOffset);
- tr.cells[0].textContent = padTo2(time.getUTCHours()) + ':' +
- padTo2(time.getUTCMinutes()) + ':' +
- padTo2(time.getSeconds());
+ tr.cells[0].textContent = padTo2(time.getUTCHours())
+ + ':'
+ + padTo2(time.getUTCMinutes())
+ + ':'
+ + padTo2(time.getSeconds());
- if ( entry.tab ) {
+ if (entry.tab) {
tr.classList.add('tab');
tr.classList.add(classNameFromTabId(entry.tab));
- if ( entry.tab === noTabId ) {
+ if (entry.tab === noTabId) {
tr.cells[1].appendChild(createHiddenTextNode('bts'));
}
}
- if ( entry.cat !== '' ) {
+ if (entry.cat !== '') {
tr.classList.add('cat_' + entry.cat);
}
@@ -293,27 +285,25 @@
};
// Reuse date objects.
- var logDate = new Date(),
- logDateTimezoneOffset = logDate.getTimezoneOffset() * 60000;
-
- /******************************************************************************/
+ let logDate = new Date();
+ let logDateTimezoneOffset = logDate.getTimezoneOffset() * 60000;
- var renderLogEntries = function(response) {
- var entries = response.entries;
- if ( entries.length === 0 ) {
+ let renderLogEntries = function (response) {
+ let entries = response.entries;
+ if (entries.length === 0) {
return;
}
// Preserve scroll position
- var height = tbody.offsetHeight;
+ let height = tbody.offsetHeight;
- var tabIds = response.tabIds;
- var n = entries.length;
- var entry;
- for ( var i = 0; i < n; i++ ) {
+ let tabIds = response.tabIds;
+ let n = entries.length;
+ let entry;
+ for (let i=0; i<n; ++i) {
entry = entries[i];
// Unlikely, but it may happen
- if ( entry.tab && tabIds.hasOwnProperty(entry.tab) === false ) {
+ if (entry.tab && tabIds.hasOwnProperty(entry.tab) === false) {
continue;
}
renderLogEntry(entries[i]);
@@ -324,85 +314,94 @@
// dynamically refreshed pages.
truncateLog(maxEntries);
- var yDelta = tbody.offsetHeight - height;
- if ( yDelta === 0 ) {
+ let yDelta = tbody.offsetHeight - height;
+ if (yDelta === 0) {
return;
}
// Chromium:
// body.scrollTop = good value
// body.parentNode.scrollTop = 0
- if ( document.body.scrollTop !== 0 ) {
- document.body.scrollTop += yDelta;
- return;
- }
+ // if (document.body.scrollTop !== 0) {
+ // document.body.scrollTop += yDelta;
+ // return;
+ // }
// Firefox:
// body.scrollTop = 0
// body.parentNode.scrollTop = good value
- var parentNode = document.body.parentNode;
- if ( parentNode && parentNode.scrollTop !== 0 ) {
+ let parentNode = document.body.parentNode;
+ if (parentNode && parentNode.scrollTop !== 0) {
parentNode.scrollTop += yDelta;
}
};
- /******************************************************************************/
+ let synchronizeTabIds = function (newTabIds) {
+ let oldTabIds = allTabIds;
+ let autoDeleteVoidRows =
+ !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows');
+ let rowVoided = false;
+ let trs;
- var synchronizeTabIds = function(newTabIds) {
- var oldTabIds = allTabIds;
- var autoDeleteVoidRows = !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows');
- var rowVoided = false;
- var trs;
- for ( var tabId in oldTabIds ) {
- if ( oldTabIds.hasOwnProperty(tabId) === false ) {
+ for (let tabId in oldTabIds) {
+ if (oldTabIds.hasOwnProperty(tabId) === false) {
continue;
}
- if ( newTabIds.hasOwnProperty(tabId) ) {
+ if (newTabIds.hasOwnProperty(tabId)) {
continue;
}
// Mark or remove voided rows
trs = uDom('.tab_' + tabId);
- if ( autoDeleteVoidRows ) {
+
+ if (autoDeleteVoidRows) {
toJunkyard(trs);
} else {
trs.removeClass('canMtx');
rowVoided = true;
}
+
// Remove popup if it is currently bound to a removed tab.
- if ( tabId === popupManager.tabId ) {
+ if (tabId === popupManager.tabId) {
popupManager.toggleOff();
}
}
- var select = document.getElementById('pageSelector');
- var selectValue = select.value;
- var tabIds = Object.keys(newTabIds).sort(function(a, b) {
+ let select = document.getElementById('pageSelector');
+ let selectValue = select.value;
+ let tabIds = Object.keys(newTabIds).sort(function (a, b) {
return newTabIds[a].localeCompare(newTabIds[b]);
});
- var option;
- for ( var i = 0, j = 2; i < tabIds.length; i++ ) {
- tabId = tabIds[i];
- if ( tabId === noTabId ) {
+
+ let i, j;
+ for (i=0, j=2; i<tabIds.length; ++i) {
+ let tabId = tabIds[i];
+ if (tabId === noTabId) {
continue;
}
- option = select.options[j];
+
+ let option = select.options[j];
j += 1;
- if ( !option ) {
+
+ if (!option) {
option = document.createElement('option');
select.appendChild(option);
}
+
option.textContent = newTabIds[tabId];
option.value = classNameFromTabId(tabId);
- if ( option.value === selectValue ) {
+
+ if (option.value === selectValue) {
option.setAttribute('selected', '');
} else {
option.removeAttribute('selected');
}
}
- while ( j < select.options.length ) {
+
+ while (j < select.options.length) {
select.removeChild(select.options[j]);
}
- if ( select.value !== selectValue ) {
+
+ if (select.value !== selectValue) {
select.selectedIndex = 0;
select.value = '';
select.options[0].setAttribute('selected', '');
@@ -414,25 +413,22 @@
return rowVoided;
};
- /******************************************************************************/
-
- var truncateLog = function(size) {
- if ( size === 0 ) {
+ let truncateLog = function (size) {
+ if (size === 0) {
size = 5000;
}
- var tbody = document.querySelector('#content tbody');
+
+ let tbody = document.querySelector('#content tbody');
size = Math.min(size, 10000);
- var tr;
- while ( tbody.childElementCount > size ) {
- tr = tbody.lastElementChild;
+
+ while (tbody.childElementCount > size) {
+ let tr = tbody.lastElementChild;
trJunkyard.push(tbody.removeChild(tr));
}
};
- /******************************************************************************/
-
- var onLogBufferRead = function(response) {
- if ( !response || response.unavailable ) {
+ let onLogBufferRead = function (response) {
+ if (!response || response.unavailable) {
readLogBufferAsync();
return;
}
@@ -441,101 +437,98 @@
noTabId = response.noTabId;
// This may have changed meanwhile
- if ( response.maxLoggedRequests !== maxEntries ) {
+ if (response.maxLoggedRequests !== maxEntries) {
maxEntries = response.maxLoggedRequests;
uDom('#maxEntries').val(maxEntries || '');
}
// Neuter rows for which a tab does not exist anymore
- var rowVoided = false;
- if ( response.tabIdsToken !== allTabIdsToken ) {
+ let rowVoided = false;
+ if (response.tabIdsToken !== allTabIdsToken) {
rowVoided = synchronizeTabIds(response.tabIds);
allTabIdsToken = response.tabIdsToken;
}
renderLogEntries(response);
- if ( rowVoided ) {
- uDom('#clean').toggleClass(
- 'disabled',
- tbody.querySelector('tr.tab:not(.canMtx)') === null
- );
+ if (rowVoided) {
+ uDom('#clean')
+ .toggleClass('disabled',
+ tbody
+ .querySelector('tr.tab:not(.canMtx)') === null);
}
// Synchronize toolbar with content of log
- uDom('#clear').toggleClass(
- 'disabled',
- tbody.querySelector('tr') === null
- );
+ uDom('#clear').toggleClass('disabled',
+ tbody.querySelector('tr') === null);
readLogBufferAsync();
};
- /******************************************************************************/
+ // This can be called only once, at init time. After that, this
+ // will be called automatically. If called after init time, this
+ // will be messy, and this would require a bit more code to ensure
+ // no multi time out events.
- // This can be called only once, at init time. After that, this will be called
- // automatically. If called after init time, this will be messy, and this would
- // require a bit more code to ensure no multi time out events.
+ let readLogBuffer = function () {
+ if (ownerId === undefined) {
+ return;
+ }
- var readLogBuffer = function() {
- if ( ownerId === undefined ) { return; }
- vAPI.messaging.send(
- 'logger-ui.js',
- { what: 'readMany', ownerId: ownerId },
- onLogBufferRead
- );
+ vAPI.messaging.send('logger-ui.js', {
+ what: 'readMany',
+ ownerId: ownerId
+ }, onLogBufferRead);
};
- var readLogBufferAsync = function() {
- if ( ownerId === undefined ) { return; }
+ let readLogBufferAsync = function () {
+ if (ownerId === undefined) {
+ return;
+ }
vAPI.setTimeout(readLogBuffer, 1200);
};
- /******************************************************************************/
+ let pageSelectorChanged = function () {
+ let style = document.getElementById('tabFilterer');
+ let tabClass = document.getElementById('pageSelector').value;
+ let sheet = style.sheet;
- var pageSelectorChanged = function() {
- var style = document.getElementById('tabFilterer');
- var tabClass = document.getElementById('pageSelector').value;
- var sheet = style.sheet;
- while ( sheet.cssRules.length !== 0 ) {
+ while (sheet.cssRules.length !== 0) {
sheet.deleteRule(0);
}
- if ( tabClass !== '' ) {
- sheet.insertRule(
- '#content table tr:not(.' + tabClass + ') { display: none; }',
- 0
- );
+
+ if (tabClass !== '') {
+ sheet.insertRule('#content table tr:not(.'
+ + tabClass
+ + ') { display: none; }', 0);
}
- uDom('#refresh').toggleClass(
- 'disabled',
- tabClass === '' || tabClass === 'tab_bts'
- );
+ uDom('#refresh').toggleClass('disabled',
+ tabClass === '' || tabClass === 'tab_bts');
};
- /******************************************************************************/
-
- var refreshTab = function() {
- var tabClass = document.getElementById('pageSelector').value;
- var matches = tabClass.match(/^tab_(.+)$/);
- if ( matches === null ) {
+ let refreshTab = function () {
+ let tabClass = document.getElementById('pageSelector').value;
+ let matches = tabClass.match(/^tab_(.+)$/);
+ if (matches === null) {
return;
}
- if ( matches[1] === 'bts' ) {
+
+ if (matches[1] === 'bts') {
return;
}
- vAPI.messaging.send(
- 'logger-ui.js',
- { what: 'forceReloadTab', tabId: matches[1] }
- );
+
+ vAPI.messaging.send('logger-ui.js', {
+ what: 'forceReloadTab',
+ tabId: matches[1]
+ });
};
- /******************************************************************************/
+ let onMaxEntriesChanged = function () {
+ let raw = uDom(this).val();
- var onMaxEntriesChanged = function() {
- var raw = uDom(this).val();
try {
maxEntries = parseInt(raw, 10);
- if ( isNaN(maxEntries) ) {
+ if (isNaN(maxEntries)) {
maxEntries = 0;
}
} catch (e) {
@@ -551,51 +544,55 @@
truncateLog(maxEntries);
};
- /******************************************************************************/
-
- var rowFilterer = (function() {
- var filters = [];
+ let rowFilterer = (function () {
+ let filters = [];
- var parseInput = function() {
+ let parseInput = function () {
filters = [];
- var rawPart, hardBeg, hardEnd;
- var raw = uDom('#filterInput').val().trim();
- var rawParts = raw.split(/\s+/);
- var reStr, reStrs = [], not = false;
- var n = rawParts.length;
- for ( var i = 0; i < n; i++ ) {
+ let rawPart, hardBeg, hardEnd;
+ let raw = uDom('#filterInput').val().trim();
+ let rawParts = raw.split(/\s+/);
+ let reStr, reStrs = [], not = false;
+ let n = rawParts.length;
+
+ for (let i=0; i<n; ++i) {
rawPart = rawParts[i];
- if ( rawPart.charAt(0) === '!' ) {
- if ( reStrs.length === 0 ) {
+ if (rawPart.charAt(0) === '!') {
+ if (reStrs.length === 0) {
not = true;
}
rawPart = rawPart.slice(1);
}
+
hardBeg = rawPart.charAt(0) === '|';
- if ( hardBeg ) {
+ if (hardBeg) {
rawPart = rawPart.slice(1);
}
+
hardEnd = rawPart.slice(-1) === '|';
- if ( hardEnd ) {
+ if (hardEnd) {
rawPart = rawPart.slice(0, -1);
}
+
if ( rawPart === '' ) {
continue;
}
- // https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions
+
reStr = rawPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- if ( hardBeg ) {
+ if (hardBeg) {
reStr = '(?:^|\\s)' + reStr;
}
- if ( hardEnd ) {
+ if (hardEnd) {
reStr += '(?:\\s|$)';
}
+
reStrs.push(reStr);
- if ( i < (n - 1) && rawParts[i + 1] === '||' ) {
+ if (i < (n - 1) && rawParts[i + 1] === '||') {
i += 1;
continue;
}
+
reStr = reStrs.length === 1 ? reStrs[0] : reStrs.join('|');
filters.push({
re: new RegExp(reStr, 'i'),
@@ -606,77 +603,85 @@
}
};
- var filterOne = function(tr, clean) {
- var ff = filters;
- var fcount = ff.length;
- if ( fcount === 0 && clean === true ) {
+ let filterOne = function (tr, clean) {
+ let ff = filters;
+ let fcount = ff.length;
+ if (fcount === 0 && clean === true) {
return;
}
- // do not filter out doc boundaries, they help separate important
- // section of log.
- var cl = tr.classList;
- if ( cl.contains('doc') ) {
+
+ // do not filter out doc boundaries, they help separate
+ // important section of log.
+ let cl = tr.classList;
+ if (cl.contains('doc')) {
return;
}
- if ( fcount === 0 ) {
+
+ if (fcount === 0) {
cl.remove('f');
return;
}
- var cc = tr.cells;
- var ccount = cc.length;
- var hit, j, f;
+
+ let cc = tr.cells;
+ let ccount = cc.length;
+ let hit, j, f;
+
// each filter expression must hit (implicit and-op)
// if...
// positive filter expression = there must one hit on any field
// negative filter expression = there must be no hit on all fields
- for ( var i = 0; i < fcount; i++ ) {
+ for (let i=0; i<fcount; ++i) {
f = ff[i];
hit = !f.r;
- for ( j = 0; j < ccount; j++ ) {
- if ( f.re.test(cc[j].textContent) ) {
+
+ for (j=0; j<ccount; ++j) {
+ if (f.re.test(cc[j].textContent)) {
hit = f.r;
break;
}
}
- if ( !hit ) {
+
+ if (!hit) {
cl.add('f');
return;
}
}
+
cl.remove('f');
};
- var filterAll = function() {
+ let filterAll = function () {
// Special case: no filter
- if ( filters.length === 0 ) {
+ if (filters.length === 0) {
uDom('#content tr').removeClass('f');
return;
}
- var tbody = document.querySelector('#content tbody');
- var rows = tbody.rows;
- var i = rows.length;
- while ( i-- ) {
+
+ let tbody = document.querySelector('#content tbody');
+ let rows = tbody.rows;
+ for (let i=rows.length-1; i>=0; --i) {
filterOne(rows[i]);
}
};
- var onFilterChangedAsync = (function() {
- var timer = null;
- var commit = function() {
+ let onFilterChangedAsync = (function () {
+ let timer = null;
+ let commit = function () {
timer = null;
parseInput();
filterAll();
};
- return function() {
- if ( timer !== null ) {
+
+ return function () {
+ if (timer !== null) {
clearTimeout(timer);
}
timer = vAPI.setTimeout(commit, 750);
};
})();
- var onFilterButton = function() {
- var cl = document.body.classList;
+ let onFilterButton = function () {
+ let cl = document.body.classList;
cl.toggle('f', cl.contains('f') === false);
};
@@ -685,113 +690,110 @@
return {
filterOne: filterOne,
- filterAll: filterAll
+ filterAll: filterAll,
};
})();
- /******************************************************************************/
-
- var toJunkyard = function(trs) {
+ let toJunkyard = function (trs) {
trs.remove();
- var i = trs.length;
- while ( i-- ) {
+ for (let i=trs.length-1; i>=0; --i) {
trJunkyard.push(trs.nodeAt(i));
}
};
- /******************************************************************************/
+ let clearBuffer = function () {
+ let tbody = document.querySelector('#content tbody');
+ let tr;
- var clearBuffer = function() {
- var tbody = document.querySelector('#content tbody');
- var tr;
- while ( tbody.firstChild !== null ) {
+ while (tbody.firstChild !== null) {
tr = tbody.lastElementChild;
trJunkyard.push(tbody.removeChild(tr));
}
+
uDom('#clear').addClass('disabled');
uDom('#clean').addClass('disabled');
};
- /******************************************************************************/
-
- var cleanBuffer = function() {
- var rows = uDom('#content tr.tab:not(.canMtx)').remove();
- var i = rows.length;
- while ( i-- ) {
+ let cleanBuffer = function () {
+ let rows = uDom('#content tr.tab:not(.canMtx)').remove();
+ for (let i=rows.length-1; i>=0; --i) {
trJunkyard.push(rows.nodeAt(i));
}
uDom('#clean').addClass('disabled');
};
- /******************************************************************************/
-
- var toggleCompactView = function() {
+ let toggleCompactView = function () {
document.body.classList.toggle('compactView');
uDom('#content table .vExpanded').removeClass('vExpanded');
};
- var toggleCompactRow = function(ev) {
+ let toggleCompactRow = function (ev) {
ev.target.parentElement.classList.toggle('vExpanded');
};
- /******************************************************************************/
-
- var popupManager = (function() {
- var realTabId = null;
- var localTabId = null;
- var container = null;
- var popup = null;
- var popupObserver = null;
- var style = null;
- var styleTemplate = [
+ let popupManager = (function () {
+ let realTabId = null;
+ let localTabId = null;
+ let container = null;
+ let popup = null;
+ let popupObserver = null;
+ let style = null;
+ let styleTemplate = [
'tr:not(.tab_{{tabId}}) {',
'cursor: not-allowed;',
'opacity: 0.2;',
'}'
].join('\n');
- var resizePopup = function() {
- if ( popup === null ) {
+ let resizePopup = function () {
+ if (popup === null) {
return;
}
- var popupBody = popup.contentWindow.document.body;
- if ( popupBody.clientWidth !== 0 && container.clientWidth !== popupBody.clientWidth ) {
+
+ let popupBody = popup.contentWindow.document.body;
+ if (popupBody.clientWidth !== 0
+ && container.clientWidth !== popupBody.clientWidth) {
container.style.setProperty('width', popupBody.clientWidth + 'px');
}
+
popup.style.removeProperty('height');
- if ( popupBody.clientHeight !== 0 && popup.clientHeight !== popupBody.clientHeight ) {
+ if (popupBody.clientHeight !== 0
+ && popup.clientHeight !== popupBody.clientHeight) {
popup.style.setProperty('height', popupBody.clientHeight + 'px');
}
- var ph = document.documentElement.clientHeight;
- var crect = container.getBoundingClientRect();
- if ( crect.height > ph ) {
+
+ let ph = document.documentElement.clientHeight;
+ let crect = container.getBoundingClientRect();
+ if (crect.height > ph) {
popup.style.setProperty('height', 'calc(' + ph + 'px - 1.8em)');
}
+
// Adjust width for presence/absence of vertical scroll bar which may
// have appeared as a result of last operation.
- var cw = container.clientWidth;
- var dw = popup.contentWindow.document.documentElement.clientWidth;
- if ( cw !== dw ) {
+ let cw = container.clientWidth;
+ let dw = popup.contentWindow.document.documentElement.clientWidth;
+ if (cw !== dw) {
container.style.setProperty('width', (2 * cw - dw) + 'px');
}
};
- var toggleSize = function() {
+ let toggleSize = function () {
container.classList.toggle('hide');
};
- var onResizeRequested = function() {
- var popupBody = popup.contentWindow.document.body;
- if ( popupBody.hasAttribute('data-resize-popup') === false ) {
+ let onResizeRequested = function () {
+ let popupBody = popup.contentWindow.document.body;
+ if (popupBody.hasAttribute('data-resize-popup') === false) {
return;
}
+
popupBody.removeAttribute('data-resize-popup');
resizePopup();
};
- var onLoad = function() {
+ let onLoad = function () {
resizePopup();
- var popupBody = popup.contentDocument.body;
+ let popupBody = popup.contentDocument.body;
popupBody.removeAttribute('data-resize-popup');
popupObserver.observe(popupBody, {
attributes: true,
@@ -799,21 +801,26 @@
});
};
- var toggleOn = function(td) {
- var tr = td.parentNode;
- var matches = tr.className.match(/(?:^| )tab_([^ ]+)/);
- if ( matches === null ) {
+ let toggleOn = function (td) {
+ let tr = td.parentNode;
+ let matches = tr.className.match(/(?:^| )tab_([^ ]+)/);
+ if (matches === null) {
return;
}
+
realTabId = localTabId = matches[1];
- if ( localTabId === 'bts' ) {
+ if (localTabId === 'bts') {
realTabId = noTabId;
}
container = document.getElementById('popupContainer');
- container.querySelector('div > span:nth-of-type(1)').addEventListener('click', toggleSize);
- container.querySelector('div > span:nth-of-type(2)').addEventListener('click', toggleOff);
+ container
+ .querySelector('div > span:nth-of-type(1)')
+ .addEventListener('click', toggleSize);
+ container
+ .querySelector('div > span:nth-of-type(2)')
+ .addEventListener('click', toggleOff);
popup = document.createElement('iframe');
popup.addEventListener('load', onLoad);
@@ -827,11 +834,15 @@
document.body.classList.add('popupOn');
};
- var toggleOff = function() {
+ let toggleOff = function () {
document.body.classList.remove('popupOn');
- container.querySelector('div > span:nth-of-type(1)').removeEventListener('click', toggleSize);
- container.querySelector('div > span:nth-of-type(2)').removeEventListener('click', toggleOff);
+ container
+ .querySelector('div > span:nth-of-type(1)')
+ .removeEventListener('click', toggleSize);
+ container
+ .querySelector('div > span:nth-of-type(2)')
+ .removeEventListener('click', toggleOff);
container.classList.remove('hide');
popup.removeEventListener('load', onLoad);
@@ -848,41 +859,45 @@
realTabId = null;
};
- var exports = {
- toggleOn: function(ev) {
- if ( realTabId === null ) {
+ let exports = {
+ toggleOn: function (ev) {
+ if (realTabId === null) {
toggleOn(ev.target);
}
},
- toggleOff: function() {
- if ( realTabId !== null ) {
+ toggleOff: function () {
+ if (realTabId !== null) {
toggleOff();
}
}
};
Object.defineProperty(exports, 'tabId', {
- get: function() { return realTabId || 0; }
+ get: function () {
+ return realTabId || 0;
+ },
});
return exports;
})();
- /******************************************************************************/
-
- var grabView = function() {
- if ( ownerId === undefined ) {
+ let grabView = function () {
+ if (ownerId === undefined) {
ownerId = Date.now();
}
readLogBufferAsync();
};
- var releaseView = function() {
- if ( ownerId === undefined ) { return; }
- vAPI.messaging.send(
- 'logger-ui.js',
- { what: 'releaseView', ownerId: ownerId }
- );
+ let releaseView = function () {
+ if (ownerId === undefined) {
+ return;
+ }
+
+ vAPI.messaging.send('logger-ui.js', {
+ what: 'releaseView',
+ ownerId: ownerId
+ });
+
ownerId = undefined;
};
@@ -891,8 +906,6 @@
// https://bugzilla.mozilla.org/show_bug.cgi?id=1398625
window.addEventListener('beforeunload', releaseView);
- /******************************************************************************/
-
readLogBuffer();
uDom('#pageSelector').on('change', pageSelectorChanged);
@@ -901,9 +914,8 @@
uDom('#clean').on('click', cleanBuffer);
uDom('#clear').on('click', clearBuffer);
uDom('#maxEntries').on('change', onMaxEntriesChanged);
- uDom('#content table').on('click', 'tr > td:nth-of-type(1)', toggleCompactRow);
- uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(2)', popupManager.toggleOn);
-
- /******************************************************************************/
-
+ uDom('#content table').on('click', 'tr > td:nth-of-type(1)',
+ toggleCompactRow);
+ uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(2)',
+ popupManager.toggleOn);
})();
diff --git a/js/logger.js b/js/logger.js
index 6f742b3..56be185 100644
--- a/js/logger.js
+++ b/js/logger.js
@@ -23,16 +23,12 @@
'use strict';
-/******************************************************************************/
-/******************************************************************************/
-
-ηMatrix.logger = (function() {
-
- var LogEntry = function(args) {
+ηMatrix.logger = (function () {
+ let LogEntry = function (args) {
this.init(args);
};
- LogEntry.prototype.init = function(args) {
+ LogEntry.prototype.init = function (args) {
this.tstamp = Date.now();
this.tab = args[0] || '';
this.cat = args[1] || '';
@@ -50,45 +46,49 @@
// unused, and thus removed from memory.
var logBufferObsoleteAfter = 30 * 1000;
- var janitor = function() {
- if (
- buffer !== null &&
- lastReadTime < (Date.now() - logBufferObsoleteAfter)
- ) {
+ var janitor = function () {
+ if (buffer !== null
+ && lastReadTime < (Date.now() - logBufferObsoleteAfter)) {
buffer = null;
writePtr = 0;
api.ownerId = undefined;
}
- if ( buffer !== null ) {
+ if (buffer !== null) {
vAPI.setTimeout(janitor, logBufferObsoleteAfter);
}
};
var api = {
ownerId: undefined,
- writeOne: function() {
- if ( buffer === null ) { return; }
- if ( writePtr === buffer.length ) {
+
+ writeOne: function () {
+ if (buffer === null) {
+ return;
+ }
+
+ if (writePtr === buffer.length) {
buffer.push(new LogEntry(arguments));
} else {
buffer[writePtr].init(arguments);
}
+
writePtr += 1;
},
- readAll: function(ownerId) {
+ readAll: function (ownerId) {
this.ownerId = ownerId;
- if ( buffer === null ) {
+
+ if (buffer === null) {
buffer = [];
vAPI.setTimeout(janitor, logBufferObsoleteAfter);
}
+
var out = buffer.slice(0, writePtr);
writePtr = 0;
lastReadTime = Date.now();
+
return out;
}
};
return api;
})();
-
-/******************************************************************************/
diff --git a/js/matrix.js b/js/matrix.js
index 6af5ab1..9a74cc7 100644
--- a/js/matrix.js
+++ b/js/matrix.js
@@ -21,7 +21,6 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global punycode */
/* jshint bitwise: false */
'use strict';
@@ -30,6 +29,9 @@
ηMatrix.Matrix = (function() {
+ Cu.import('chrome://ematrix/content/lib/Punycode.jsm');
+ Cu.import('chrome://ematrix/content/lib/UriTools.jsm');
+
/******************************************************************************/
var ηm = ηMatrix;
@@ -179,7 +181,7 @@
if ( srcHostname === '*' || desHostname === '*' || desHostname === '1st-party' ) {
return '';
}
- var ηmuri = ηm.URI;
+ var ηmuri = UriTools;
var srcDomain = ηmuri.domainFromHostname(srcHostname) || srcHostname;
var desDomain = ηmuri.domainFromHostname(desHostname) || desHostname;
return desDomain === srcDomain ? desDomain : '';
@@ -607,8 +609,8 @@
val = this.evaluateCell(srcHostname, desHostname, type);
if ( val === 0 ) { continue; }
out.push(
- punycode.toUnicode(srcHostname) + ' ' +
- punycode.toUnicode(desHostname) + ' ' +
+ Punycode.toUnicode(srcHostname) + ' ' +
+ Punycode.toUnicode(desHostname) + ' ' +
type + ' ' +
stateToNameMap.get(val)
);
@@ -694,7 +696,7 @@
switchName = fieldVal.slice(0, pos);
}
if ( switchBitOffsets.has(switchName) ) {
- srcHostname = punycode.toASCII(fields[1]);
+ srcHostname = Punycode.toASCII(fields[1]);
// No state field: reject
fieldVal = fields[2];
@@ -737,8 +739,8 @@
// Lines with invalid syntax silently ignored
- srcHostname = punycode.toASCII(fields[0]);
- desHostname = punycode.toASCII(fields[1]);
+ srcHostname = Punycode.toASCII(fields[0]);
+ desHostname = Punycode.toASCII(fields[1]);
fieldVal = fields[2];
diff --git a/js/messaging.js b/js/messaging.js
index 3252872..4864e90 100644
--- a/js/messaging.js
+++ b/js/messaging.js
@@ -30,6 +30,8 @@
(function() {
+ Cu.import('chrome://ematrix/content/lib/UriTools.jsm');
+
var ηm = ηMatrix;
/******************************************************************************/
@@ -220,7 +222,6 @@
r.rows['1st-party'] = new RowSnapshot(r.scope, '1st-party', '1st-party');
r.rowCount += 1;
- var ηmuri = ηm.URI;
var reqType, reqHostname, reqDomain;
var desHostname;
var row, typeIndex;
@@ -236,7 +237,7 @@
if ( reqHostname === '' ) {
reqHostname = pageStore.pageHostname;
}
- reqDomain = ηmuri.domainFromHostname(reqHostname) || reqHostname;
+ reqDomain = UriTools.domainFromHostname(reqHostname) || reqHostname;
// We want rows of self and ancestors
desHostname = reqHostname;
@@ -404,9 +405,9 @@
var foundInlineCode = function(tabId, pageStore, details, type) {
if ( pageStore === null ) { return; }
- var pageHostname = pageStore.pageHostname,
- ηmuri = ηm.URI.set(details.documentURI),
- frameURL = ηmuri.normalizedURI();
+ let pageHostname = pageStore.pageHostname;
+ let ηmuri = UriTools.set(details.documentURI);
+ let frameURL = UriTools.normalizedURI();
var blocked = details.blocked;
if ( blocked === undefined ) {
@@ -433,7 +434,7 @@
var blocked = ηm.mustBlock(
tabContext.rootHostname,
- ηm.URI.hostnameFromURI(originURL),
+ UriTools.hostnameFromURI(originURL),
'cookie'
);
@@ -553,7 +554,7 @@
case 'securityPolicyViolation':
if ( request.directive === 'worker-src' ) {
- var url = ηm.URI.hostnameFromURI(request.blockedURI) !== '' ?
+ var url = UriTools.hostnameFromURI(request.blockedURI) !== '' ?
request.blockedURI :
request.documentURI;
if ( pageStore !== null ) {
@@ -716,7 +717,7 @@
/******************************************************************************/
var prepEntries = function(entries) {
- var ηmuri = ηm.URI;
+ var ηmuri = UriTools;
var entry;
for ( var k in entries ) {
if ( entries.hasOwnProperty(k) === false ) {
diff --git a/js/pagestats.js b/js/pagestats.js
index d5c2cdd..3490071 100644
--- a/js/pagestats.js
+++ b/js/pagestats.js
@@ -27,6 +27,8 @@
ηMatrix.pageStoreFactory = (function() {
+ Cu.import('chrome://ematrix/content/lib/UriTools.jsm');
+
/******************************************************************************/
var ηm = ηMatrix;
@@ -179,7 +181,7 @@
request.toFilter.length !== 0
) {
var roothn = tabContext.rootHostname,
- hnFromURI = ηm.URI.hostnameFromURI,
+ hnFromURI = UriTools.hostnameFromURI,
tMatrix = ηm.tMatrix;
for ( entry of request.toFilter ) {
if ( tMatrix.mustBlock(roothn, hnFromURI(entry.url), entry.type) === false ) {
@@ -216,7 +218,7 @@
// - remember which hostname/type were seen
// - count the number of distinct URLs for any given
// hostname-type pair
- var hostname = ηm.URI.hostnameFromURI(url),
+ var hostname = UriTools.hostnameFromURI(url),
key = hostname + ' ' + type,
uids = this.hostnameTypeCells.get(key);
if ( uids === undefined ) {
diff --git a/js/popup.js b/js/popup.js
index 2197c5c..a5a48d7 100644
--- a/js/popup.js
+++ b/js/popup.js
@@ -21,32 +21,28 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global punycode, uDom */
-/* jshint esnext: true, bitwise: false */
-
'use strict';
-/******************************************************************************/
-/******************************************************************************/
-
-(function() {
+(function () {
- /******************************************************************************/
- /******************************************************************************/
+ Cu.import('chrome://ematrix/content/lib/Punycode.jsm');
// Stuff which is good to do very early so as to avoid visual glitches.
-
- (function() {
- var paneContentPaddingTop = vAPI.localStorage.getItem('paneContentPaddingTop'),
- touchDevice = vAPI.localStorage.getItem('touchDevice');
-
- if ( typeof paneContentPaddingTop === 'string' ) {
- document.querySelector('.paneContent').style.setProperty(
- 'padding-top',
- paneContentPaddingTop
- );
+ (function () {
+ let paneContentPaddingTop =
+ vAPI.localStorage.getItem('paneContentPaddingTop');
+ let touchDevice = vAPI.localStorage.getItem('touchDevice');
+
+ if (typeof paneContentPaddingTop === 'string') {
+ document
+ .querySelector('.paneContent')
+ .style
+ .setProperty('padding-top',
+ paneContentPaddingTop);
}
- if ( touchDevice === 'true' ) {
+
+ /* This is for CSS */
+ if (touchDevice === 'true') {
document.body.setAttribute('data-touch', 'true');
} else {
document.addEventListener('touchstart', function onTouched(ev) {
@@ -58,54 +54,58 @@
}
})();
- var popupWasResized = function() {
+ let popupWasResized = function () {
document.body.setAttribute('data-resize-popup', '');
};
- var resizePopup = (function() {
- var timer;
- var fix = function() {
+ let resizePopup = (function () {
+ let timer;
+
+ let fix = function () {
timer = undefined;
- var doc = document;
+ let doc = document;
// Manually adjust the position of the main matrix according to the
// height of the toolbar/matrix header.
- var paddingTop = (doc.querySelector('.paneHead').clientHeight + 2) + 'px',
- paneContent = doc.querySelector('.paneContent');
- if ( paddingTop !== paneContent.style.paddingTop ) {
+ let paddingTop =
+ (doc.querySelector('.paneHead').clientHeight + 2) + 'px';
+ let paneContent = doc.querySelector('.paneContent');
+
+ if (paddingTop !== paneContent.style.paddingTop) {
paneContent.style.setProperty('padding-top', paddingTop);
vAPI.localStorage.setItem('paneContentPaddingTop', paddingTop);
}
- document.body.classList.toggle(
- 'hConstrained',
- window.innerWidth < document.body.clientWidth
- );
+
+ document
+ .body
+ .classList
+ .toggle('hConstrained',
+ window.innerWidth < document.body.clientWidth);
+
popupWasResized();
};
- return function() {
- if ( timer !== undefined ) {
+
+ return function () {
+ if (timer !== undefined) {
clearTimeout(timer);
}
timer = vAPI.setTimeout(fix, 97);
};
})();
- /******************************************************************************/
- /******************************************************************************/
-
// Must be consistent with definitions in matrix.js
- var Dark = 0x80;
- var Red = 1;
- var Green = 2;
- var DarkRed = Dark | Red;
- var DarkGreen = Dark | Green;
+ let Dark = 0x80;
+ let Red = 1;
+ let Green = 2;
+ let DarkRed = Dark | Red;
+ let DarkGreen = Dark | Green;
- var matrixSnapshot = {};
- var groupsSnapshot = [];
- var allHostnamesSnapshot = 'do not leave this initial string empty';
+ let matrixSnapshot = {};
+ let groupsSnapshot = [];
+ let allHostnamesSnapshot = 'do not leave this initial string empty';
- var matrixCellHotspots = null;
+ let matrixCellHotspots = null;
- var matrixHeaderPrettyNames = {
+ let matrixHeaderPrettyNames = {
'all': '',
'cookie': '',
'css': '',
@@ -117,41 +117,37 @@
'other': ''
};
- var firstPartyLabel = '';
- var blacklistedHostnamesLabel = '';
+ let firstPartyLabel = '';
+ let blacklistedHostnamesLabel = '';
- var expandosIdGenerator = 1;
- var nodeToExpandosMap = (function() {
- if ( typeof window.Map === 'function' ) {
+ let expandosIdGenerator = 1;
+ let nodeToExpandosMap = (function () {
+ if (typeof window.Map === 'function') {
return new window.Map();
}
})();
- var expandosFromNode = function(node) {
- if (
- node instanceof HTMLElement === false &&
- typeof node.nodeAt === 'function'
- ) {
+ let expandosFromNode = function (node) {
+ if (node instanceof HTMLElement === false
+ && typeof node.nodeAt === 'function') {
node = node.nodeAt(0);
}
- if ( nodeToExpandosMap ) {
- var expandosId = node.getAttribute('data-expandos');
- if ( !expandosId ) {
+ if (nodeToExpandosMap) {
+ let expandosId = node.getAttribute('data-expandos');
+ if (!expandosId) {
expandosId = '' + (expandosIdGenerator++);
node.setAttribute('data-expandos', expandosId);
}
- var expandos = nodeToExpandosMap.get(expandosId);
- if ( expandos === undefined ) {
- nodeToExpandosMap.set(expandosId, (expandos = Object.create(null)));
+ let expandos = nodeToExpandosMap.get(expandosId);
+ if (expandos === undefined) {
+ expandos = Object.create(null);
+ nodeToExpandosMap.set(expandosId, expandos);
}
return expandos;
}
return node;
};
- /******************************************************************************/
- /******************************************************************************/
-
function getUserSetting(setting) {
return matrixSnapshot.userSettings[setting];
}
@@ -165,31 +161,22 @@
});
}
- /******************************************************************************/
-
function getUISetting(setting) {
- var r = vAPI.localStorage.getItem(setting);
- if ( typeof r !== 'string' ) {
+ let r = vAPI.localStorage.getItem(setting);
+ if (typeof r !== 'string') {
return undefined;
}
return JSON.parse(r);
}
function setUISetting(setting, value) {
- vAPI.localStorage.setItem(
- setting,
- JSON.stringify(value)
- );
+ vAPI.localStorage.setItem(setting, JSON.stringify(value));
}
- /******************************************************************************/
-
function updateMatrixSnapshot() {
matrixSnapshotPoller.pollNow();
}
- /******************************************************************************/
-
// For display purpose, create four distinct groups of rows:
// 0th: literal "1st-party" row
// 1st: page domain's related
@@ -201,76 +188,79 @@
// Try to not reshuffle groups around while popup is opened if
// no new hostname added.
- var latestDomainListSnapshot = Object.keys(matrixSnapshot.rows).sort().join();
- if ( latestDomainListSnapshot === allHostnamesSnapshot ) {
+ let latestDomainListSnapshot =
+ Object.keys(matrixSnapshot.rows).sort().join();
+ if (latestDomainListSnapshot === allHostnamesSnapshot) {
return groupsSnapshot;
}
allHostnamesSnapshot = latestDomainListSnapshot;
// First, group according to whether at least one node in the domain
// hierarchy is white or blacklisted
- var pageDomain = matrixSnapshot.domain;
- var rows = matrixSnapshot.rows;
- var anyTypeOffset = matrixSnapshot.headerIndices.get('*');
- var hostname, domain;
- var row, color, count, groupIndex;
- var domainToGroupMap = {};
+ let pageDomain = matrixSnapshot.domain;
+ let rows = matrixSnapshot.rows;
+ let anyTypeOffset = matrixSnapshot.headerIndices.get('*');
+ let hostname, domain;
+ let row, color, count;
+ let domainToGroupMap = {};
// These have hard-coded position which cannot be overriden
domainToGroupMap['1st-party'] = 0;
domainToGroupMap[pageDomain] = 1;
// 1st pass: domain wins if it has an explicit rule or a count
- for ( hostname in rows ) {
- if ( rows.hasOwnProperty(hostname) === false ) {
+ for (hostname in rows) {
+ if (rows.hasOwnProperty(hostname) === false) {
continue;
}
- if ( hostname === '*' || hostname === '1st-party' ) {
+ if (hostname === '*' || hostname === '1st-party') {
continue;
}
domain = rows[hostname].domain;
- if ( domain === pageDomain || hostname !== domain ) {
+ if (domain === pageDomain || hostname !== domain) {
continue;
}
row = rows[domain];
color = row.temporary[anyTypeOffset];
- if ( color === DarkGreen ) {
+ if (color === DarkGreen) {
domainToGroupMap[domain] = 2;
continue;
}
- if ( color === DarkRed ) {
+ if (color === DarkRed) {
domainToGroupMap[domain] = 4;
continue;
}
count = row.counts[anyTypeOffset];
- if ( count !== 0 ) {
+ if (count !== 0) {
domainToGroupMap[domain] = 3;
continue;
}
}
+
// 2nd pass: green wins
- for ( hostname in rows ) {
- if ( rows.hasOwnProperty(hostname) === false ) {
+ for (hostname in rows) {
+ if (rows.hasOwnProperty(hostname) === false) {
continue;
}
row = rows[hostname];
domain = row.domain;
- if ( domainToGroupMap.hasOwnProperty(domain) ) {
+ if (domainToGroupMap.hasOwnProperty(domain)) {
continue;
}
color = row.temporary[anyTypeOffset];
- if ( color === DarkGreen ) {
+ if (color === DarkGreen) {
domainToGroupMap[domain] = 2;
}
}
+
// 3rd pass: gray with count wins
- for ( hostname in rows ) {
- if ( rows.hasOwnProperty(hostname) === false ) {
+ for (hostname in rows) {
+ if (rows.hasOwnProperty(hostname) === false) {
continue;
}
row = rows[hostname];
domain = row.domain;
- if ( domainToGroupMap.hasOwnProperty(domain) ) {
+ if (domainToGroupMap.hasOwnProperty(domain)) {
continue;
}
color = row.temporary[anyTypeOffset];
@@ -279,47 +269,51 @@
domainToGroupMap[domain] = 3;
}
}
+
// 4th pass: red wins whatever is left
- for ( hostname in rows ) {
- if ( rows.hasOwnProperty(hostname) === false ) {
+ for (hostname in rows) {
+ if (rows.hasOwnProperty(hostname) === false) {
continue;
}
row = rows[hostname];
domain = row.domain;
- if ( domainToGroupMap.hasOwnProperty(domain) ) {
+ if (domainToGroupMap.hasOwnProperty(domain)) {
continue;
}
color = row.temporary[anyTypeOffset];
- if ( color === DarkRed ) {
+ if (color === DarkRed) {
domainToGroupMap[domain] = 4;
}
}
+
// 5th pass: gray wins whatever is left
- for ( hostname in rows ) {
- if ( rows.hasOwnProperty(hostname) === false ) {
+ for (hostname in rows) {
+ if (rows.hasOwnProperty(hostname) === false) {
continue;
}
domain = rows[hostname].domain;
- if ( domainToGroupMap.hasOwnProperty(domain) ) {
+ if (domainToGroupMap.hasOwnProperty(domain)) {
continue;
}
domainToGroupMap[domain] = 3;
}
// Last pass: put each domain in a group
- var groups = [ {}, {}, {}, {}, {} ];
- var group;
- for ( hostname in rows ) {
- if ( rows.hasOwnProperty(hostname) === false ) {
+ let groups = [
+ {}, {}, {}, {}, {}
+ ];
+
+ for (hostname in rows) {
+ if (rows.hasOwnProperty(hostname) === false) {
continue;
}
if ( hostname === '*' ) {
continue;
}
domain = rows[hostname].domain;
- groupIndex = domainToGroupMap[domain];
- group = groups[groupIndex];
- if ( group.hasOwnProperty(domain) === false ) {
+ let groupIndex = domainToGroupMap[domain];
+ let group = groups[groupIndex];
+ if (group.hasOwnProperty(domain) === false) {
group[domain] = {};
}
group[domain][hostname] = true;
@@ -330,41 +324,40 @@
return groups;
}
- /******************************************************************************/
-
// helpers
-
function getTemporaryColor(hostname, type) {
- return matrixSnapshot.rows[hostname].temporary[matrixSnapshot.headerIndices.get(type)];
+ return matrixSnapshot
+ .rows[hostname]
+ .temporary[matrixSnapshot.headerIndices.get(type)];
}
function getPermanentColor(hostname, type) {
- return matrixSnapshot.rows[hostname].permanent[matrixSnapshot.headerIndices.get(type)];
+ return matrixSnapshot
+ .rows[hostname]
+ .permanent[matrixSnapshot.headerIndices.get(type)];
}
function addCellClass(cell, hostname, type) {
- var cl = cell.classList;
+ let cl = cell.classList;
cl.add('matCell');
cl.add('t' + getTemporaryColor(hostname, type).toString(16));
cl.add('p' + getPermanentColor(hostname, type).toString(16));
}
- /******************************************************************************/
-
// This is required for when we update the matrix while it is open:
// the user might have collapsed/expanded one or more domains, and we don't
// want to lose all his hardwork.
function getCollapseState(domain) {
- var states = getUISetting('popupCollapseSpecificDomains');
- if ( typeof states === 'object' && states[domain] !== undefined ) {
+ let states = getUISetting('popupCollapseSpecificDomains');
+ if (typeof states === 'object' && states[domain] !== undefined) {
return states[domain];
}
return matrixSnapshot.collapseAllDomains === true;
}
function toggleCollapseState(elem) {
- if ( elem.ancestors('#matHead.collapsible').length > 0 ) {
+ if (elem.ancestors('#matHead.collapsible').length > 0) {
toggleMainCollapseState(elem);
} else {
toggleSpecificCollapseState(elem);
@@ -373,18 +366,21 @@
}
function toggleMainCollapseState(uelem) {
- var matHead = uelem.ancestors('#matHead.collapsible').toggleClass('collapsed');
- var collapsed = matrixSnapshot.collapseAllDomains = matHead.hasClass('collapsed');
- uDom('#matList .matSection.collapsible').toggleClass('collapsed', collapsed);
+ let matHead =
+ uelem.ancestors('#matHead.collapsible').toggleClass('collapsed');
+ let collapsed =
+ matrixSnapshot.collapseAllDomains = matHead.hasClass('collapsed');
+
+ uDom('#matList .matSection.collapsible')
+ .toggleClass('collapsed', collapsed);
setUserSetting('popupCollapseAllDomains', collapsed);
- var specificCollapseStates = getUISetting('popupCollapseSpecificDomains') || {};
- var domains = Object.keys(specificCollapseStates);
- var i = domains.length;
- var domain;
- while ( i-- ) {
- domain = domains[i];
- if ( specificCollapseStates[domain] === collapsed ) {
+ let specificCollapseStates =
+ getUISetting('popupCollapseSpecificDomains') || {};
+ let domains = Object.keys(specificCollapseStates);
+ for (let i=domains.length-1; i>=0; --i) {
+ let domain = domains[i];
+ if (specificCollapseStates[domain] === collapsed) {
delete specificCollapseStates[domain];
}
}
@@ -394,71 +390,79 @@
function toggleSpecificCollapseState(uelem) {
// Remember collapse state forever, but only if it is different
// from main collapse switch.
- var section = uelem.ancestors('.matSection.collapsible').toggleClass('collapsed'),
- domain = expandosFromNode(section).domain,
- collapsed = section.hasClass('collapsed'),
- mainCollapseState = matrixSnapshot.collapseAllDomains === true,
- specificCollapseStates = getUISetting('popupCollapseSpecificDomains') || {};
- if ( collapsed !== mainCollapseState ) {
+ let section =
+ uelem.ancestors('.matSection.collapsible').toggleClass('collapsed');
+ let domain = expandosFromNode(section).domain;
+ let collapsed = section.hasClass('collapsed');
+ let mainCollapseState = matrixSnapshot.collapseAllDomains === true;
+ let specificCollapseStates =
+ getUISetting('popupCollapseSpecificDomains') || {};
+
+ if (collapsed !== mainCollapseState) {
specificCollapseStates[domain] = collapsed;
- setUISetting('popupCollapseSpecificDomains', specificCollapseStates);
- } else if ( specificCollapseStates[domain] !== undefined ) {
+ setUISetting('popupCollapseSpecificDomains',
+ specificCollapseStates);
+ } else if (specificCollapseStates[domain] !== undefined) {
delete specificCollapseStates[domain];
- setUISetting('popupCollapseSpecificDomains', specificCollapseStates);
+ setUISetting('popupCollapseSpecificDomains',
+ specificCollapseStates);
}
}
- /******************************************************************************/
-
// Update count value of matrix cells(s)
function updateMatrixCounts() {
- var matCells = uDom('.matrix .matRow.rw > .matCell'),
- i = matCells.length,
- matRow, matCell, count, counts,
- headerIndices = matrixSnapshot.headerIndices,
- rows = matrixSnapshot.rows,
- expandos;
- while ( i-- ) {
+ let matCells = uDom('.matrix .matRow.rw > .matCell');
+ let matRow, matCell, count, counts;
+ let headerIndices = matrixSnapshot.headerIndices;
+ let rows = matrixSnapshot.rows;
+ let expandos;
+
+ for (let i=matCells.length-1; i>=0; --i) {
matCell = matCells.nodeAt(i);
expandos = expandosFromNode(matCell);
- if ( expandos.hostname === '*' || expandos.reqType === '*' ) {
+ if (expandos.hostname === '*' || expandos.reqType === '*') {
continue;
}
matRow = matCell.parentNode;
counts = matRow.classList.contains('meta') ? 'totals' : 'counts';
- count = rows[expandos.hostname][counts][headerIndices.get(expandos.reqType)];
- if ( count === expandos.count ) { continue; }
+ count = rows[expandos.hostname][counts][headerIndices
+ .get(expandos.reqType)];
+ if (count === expandos.count) {
+ continue;
+ }
expandos.count = count;
matCell.textContent = cellTextFromCount(count);
}
}
function cellTextFromCount(count) {
- if ( count === 0 ) { return '\u00A0'; }
- if ( count < 100 ) { return count; }
+ if (count === 0) {
+ return '\u00A0';
+ }
+
+ if (count < 100) {
+ return count;
+ }
+
return '99+';
}
- /******************************************************************************/
-
// Update color of matrix cells(s)
// Color changes when rules change
function updateMatrixColors() {
- var cells = uDom('.matrix .matRow.rw > .matCell').removeClass(),
- i = cells.length,
- cell, expandos;
- while ( i-- ) {
+ let cells = uDom('.matrix .matRow.rw > .matCell').removeClass();
+ let cell, expandos;
+ for (let i=cells.length-1; i>=0; --i) {
cell = cells.nodeAt(i);
expandos = expandosFromNode(cell);
addCellClass(cell, expandos.hostname, expandos.reqType);
}
+
popupWasResized();
}
- /******************************************************************************/
-
// Update behavior of matrix:
// - Whether a section is collapsible or not. It is collapsible if:
// - It has at least one subdomain AND
@@ -467,57 +471,68 @@
function updateMatrixBehavior() {
matrixList = matrixList || uDom('#matList');
- var sections = matrixList.descendants('.matSection');
- var i = sections.length;
- var section, subdomainRows, j, subdomainRow;
- while ( i-- ) {
+ let sections = matrixList.descendants('.matSection');
+ let section, subdomainRows, subdomainRow;
+ for (let i=sections.length-1; i>=0; --i) {
section = sections.at(i);
subdomainRows = section.descendants('.l2:not(.g4)');
- j = subdomainRows.length;
- while ( j-- ) {
+ for (let j=subdomainRows.length-1; j>=0; --j) {
subdomainRow = subdomainRows.at(j);
- subdomainRow.toggleClass('collapsible', subdomainRow.descendants('.t81,.t82').length === 0);
+ subdomainRow.toggleClass('collapsible',
+ subdomainRow
+ .descendants('.t81,.t82')
+ .length === 0);
}
- section.toggleClass('collapsible', subdomainRows.filter('.collapsible').length > 0);
+
+ section.toggleClass('collapsible',
+ subdomainRows.filter('.collapsible').length > 0);
}
}
- /******************************************************************************/
-
// handle user interaction with filters
function getCellAction(hostname, type, leaning) {
- var temporaryColor = getTemporaryColor(hostname, type);
- var hue = temporaryColor & 0x03;
+ let temporaryColor = getTemporaryColor(hostname, type);
+ let hue = temporaryColor & 0x03;
+
// Special case: root toggle only between two states
- if ( type === '*' && hostname === '*' ) {
- return hue === Green ? 'blacklistMatrixCell' : 'whitelistMatrixCell';
+ if (type === '*' && hostname === '*') {
+ return hue === Green ?
+ 'blacklistMatrixCell' :
+ 'whitelistMatrixCell';
}
+
// When explicitly blocked/allowed, can only graylist
- var saturation = temporaryColor & 0x80;
- if ( saturation === Dark ) {
+ let saturation = temporaryColor & 0x80;
+ if (saturation === Dark) {
return 'graylistMatrixCell';
}
- return leaning === 'whitelisting' ? 'whitelistMatrixCell' : 'blacklistMatrixCell';
+
+ return leaning === 'whitelisting' ?
+ 'whitelistMatrixCell' :
+ 'blacklistMatrixCell';
}
function handleFilter(button, leaning) {
// our parent cell knows who we are
- var cell = button.ancestors('div.matCell'),
- expandos = expandosFromNode(cell),
- type = expandos.reqType,
- desHostname = expandos.hostname;
+ let cell = button.ancestors('div.matCell');
+ let expandos = expandosFromNode(cell);
+ let type = expandos.reqType;
+ let desHostname = expandos.hostname;
+
// https://github.com/gorhill/uMatrix/issues/24
// No hostname can happen -- like with blacklist meta row
- if ( desHostname === '' ) {
+ if (desHostname === '') {
return;
}
- var request = {
+
+ let request = {
what: getCellAction(desHostname, type, leaning),
srcHostname: matrixSnapshot.scope,
desHostname: desHostname,
type: type
};
+
vAPI.messaging.send('popup.js', request, updateMatrixSnapshot);
}
@@ -529,164 +544,180 @@
handleFilter(button, 'blacklisting');
}
- /******************************************************************************/
-
- var matrixRowPool = [];
- var matrixSectionPool = [];
- var matrixGroupPool = [];
- var matrixRowTemplate = null;
- var matrixList = null;
+ let matrixRowPool = [];
+ let matrixSectionPool = [];
+ let matrixGroupPool = [];
+ let matrixRowTemplate = null;
+ let matrixList = null;
- var startMatrixUpdate = function() {
+ let startMatrixUpdate = function () {
matrixList = matrixList || uDom('#matList');
matrixList.detach();
- var rows = matrixList.descendants('.matRow');
+ let rows = matrixList.descendants('.matRow');
rows.detach();
matrixRowPool = matrixRowPool.concat(rows.toArray());
- var sections = matrixList.descendants('.matSection');
+ let sections = matrixList.descendants('.matSection');
sections.detach();
matrixSectionPool = matrixSectionPool.concat(sections.toArray());
- var groups = matrixList.descendants('.matGroup');
+ let groups = matrixList.descendants('.matGroup');
groups.detach();
matrixGroupPool = matrixGroupPool.concat(groups.toArray());
};
- var endMatrixUpdate = function() {
- // https://github.com/gorhill/httpswitchboard/issues/246
- // If the matrix has no rows, we need to insert a dummy one, invisible,
- // to ensure the extension pop-up is properly sized. This is needed because
- // the header pane's `position` property is `fixed`, which means it doesn't
- // affect layout size, hence the matrix header row will be truncated.
- if ( matrixSnapshot.rowCount <= 1 ) {
+ let endMatrixUpdate = function () {
+ // https://github.com/gorhill/httpswitchboard/issues/246 If
+ // the matrix has no rows, we need to insert a dummy one,
+ // invisible, to ensure the extension pop-up is properly
+ // sized. This is needed because the header pane's `position`
+ // property is `fixed`, which means it doesn't affect layout
+ // size, hence the matrix header row will be truncated.
+ if (matrixSnapshot.rowCount <= 1) {
matrixList.append(createMatrixRow().css('visibility', 'hidden'));
}
+
updateMatrixBehavior();
matrixList.css('display', '');
matrixList.appendTo('.paneContent');
};
- var createMatrixGroup = function() {
- var group = matrixGroupPool.pop();
- if ( group ) {
+ let createMatrixGroup = function () {
+ let group = matrixGroupPool.pop();
+ if (group) {
return uDom(group).removeClass().addClass('matGroup');
}
return uDom(document.createElement('div')).addClass('matGroup');
};
- var createMatrixSection = function() {
- var section = matrixSectionPool.pop();
- if ( section ) {
+ let createMatrixSection = function () {
+ let section = matrixSectionPool.pop();
+ if (section) {
return uDom(section).removeClass().addClass('matSection');
}
return uDom(document.createElement('div')).addClass('matSection');
};
- var createMatrixRow = function() {
- var row = matrixRowPool.pop();
- if ( row ) {
+ let createMatrixRow = function () {
+ let row = matrixRowPool.pop();
+ if (row) {
row.style.visibility = '';
row = uDom(row);
row.descendants('.matCell').removeClass().addClass('matCell');
row.removeClass().addClass('matRow');
return row;
}
- if ( matrixRowTemplate === null ) {
+
+ if (matrixRowTemplate === null) {
matrixRowTemplate = uDom('#templates .matRow');
}
+
return matrixRowTemplate.clone();
};
- /******************************************************************************/
-
function renderMatrixHeaderRow() {
- var matHead = uDom('#matHead.collapsible');
- matHead.toggleClass('collapsed', matrixSnapshot.collapseAllDomains === true);
- var cells = matHead.descendants('.matCell'), cell, expandos;
- cell = cells.nodeAt(0);
- expandos = expandosFromNode(cell);
+ let matHead = uDom('#matHead.collapsible');
+ matHead.toggleClass('collapsed',
+ matrixSnapshot.collapseAllDomains === true);
+
+ let cells = matHead.descendants('.matCell')
+ let cell = cells.nodeAt(0);
+ let expandos = expandosFromNode(cell);
expandos.reqType = '*';
expandos.hostname = '*';
addCellClass(cell, '*', '*');
+
cell = cells.nodeAt(1);
expandos = expandosFromNode(cell);
expandos.reqType = 'cookie';
expandos.hostname = '*';
addCellClass(cell, '*', 'cookie');
+
cell = cells.nodeAt(2);
expandos = expandosFromNode(cell);
expandos.reqType = 'css';
expandos.hostname = '*';
addCellClass(cell, '*', 'css');
+
cell = cells.nodeAt(3);
expandos = expandosFromNode(cell);
expandos.reqType = 'image';
expandos.hostname = '*';
addCellClass(cell, '*', 'image');
+
cell = cells.nodeAt(4);
expandos = expandosFromNode(cell);
expandos.reqType = 'media';
expandos.hostname = '*';
addCellClass(cell, '*', 'media');
+
cell = cells.nodeAt(5);
expandos = expandosFromNode(cell);
expandos.reqType = 'script';
expandos.hostname = '*';
addCellClass(cell, '*', 'script');
+
cell = cells.nodeAt(6);
expandos = expandosFromNode(cell);
expandos.reqType = 'xhr';
expandos.hostname = '*';
addCellClass(cell, '*', 'xhr');
+
cell = cells.nodeAt(7);
expandos = expandosFromNode(cell);
expandos.reqType = 'frame';
expandos.hostname = '*';
addCellClass(cell, '*', 'frame');
+
cell = cells.nodeAt(8);
expandos = expandosFromNode(cell);
expandos.reqType = 'other';
expandos.hostname = '*';
addCellClass(cell, '*', 'other');
+
uDom('#matHead .matRow').css('display', '');
}
- /******************************************************************************/
-
function renderMatrixCellDomain(cell, domain) {
- var expandos = expandosFromNode(cell);
+ let expandos = expandosFromNode(cell);
expandos.hostname = domain;
expandos.reqType = '*';
addCellClass(cell.nodeAt(0), domain, '*');
- var contents = cell.contents();
+
+ let contents = cell.contents();
contents.nodeAt(0).textContent = domain === '1st-party' ?
firstPartyLabel :
- punycode.toUnicode(domain);
+ Punycode.toUnicode(domain);
+
contents.nodeAt(1).textContent = ' ';
}
function renderMatrixCellSubdomain(cell, domain, subomain) {
- var expandos = expandosFromNode(cell);
+ let expandos = expandosFromNode(cell);
expandos.hostname = subomain;
expandos.reqType = '*';
addCellClass(cell.nodeAt(0), subomain, '*');
- var contents = cell.contents();
- contents.nodeAt(0).textContent = punycode.toUnicode(subomain.slice(0, subomain.lastIndexOf(domain)-1)) + '.';
- contents.nodeAt(1).textContent = punycode.toUnicode(domain);
+
+ let contents = cell.contents();
+ contents.nodeAt(0).textContent =
+ Punycode.toUnicode(subomain.slice(0,
+ subomain.lastIndexOf(domain)-1))
+ + '.';
+ contents.nodeAt(1).textContent = Punycode.toUnicode(domain);
}
function renderMatrixMetaCellDomain(cell, domain) {
- var expandos = expandosFromNode(cell);
+ let expandos = expandosFromNode(cell);
expandos.hostname = domain;
expandos.reqType = '*';
addCellClass(cell.nodeAt(0), domain, '*');
- var contents = cell.contents();
- contents.nodeAt(0).textContent = '\u2217.' + punycode.toUnicode(domain);
+
+ let contents = cell.contents();
+ contents.nodeAt(0).textContent = '\u2217.' + Punycode.toUnicode(domain);
contents.nodeAt(1).textContent = ' ';
}
function renderMatrixCellType(cell, hostname, type, count) {
- var node = cell.nodeAt(0),
- expandos = expandosFromNode(node);
+ let node = cell.nodeAt(0);
+ let expandos = expandosFromNode(node);
expandos.hostname = hostname;
expandos.reqType = type;
expandos.count = count;
@@ -695,51 +726,55 @@
}
function renderMatrixCellTypes(cells, hostname, countName) {
- var counts = matrixSnapshot.rows[hostname][countName];
- var headerIndices = matrixSnapshot.headerIndices;
- renderMatrixCellType(cells.at(1), hostname, 'cookie', counts[headerIndices.get('cookie')]);
- renderMatrixCellType(cells.at(2), hostname, 'css', counts[headerIndices.get('css')]);
- renderMatrixCellType(cells.at(3), hostname, 'image', counts[headerIndices.get('image')]);
- renderMatrixCellType(cells.at(4), hostname, 'media', counts[headerIndices.get('media')]);
- renderMatrixCellType(cells.at(5), hostname, 'script', counts[headerIndices.get('script')]);
- renderMatrixCellType(cells.at(6), hostname, 'xhr', counts[headerIndices.get('xhr')]);
- renderMatrixCellType(cells.at(7), hostname, 'frame', counts[headerIndices.get('frame')]);
- renderMatrixCellType(cells.at(8), hostname, 'other', counts[headerIndices.get('other')]);
+ let counts = matrixSnapshot.rows[hostname][countName];
+ let headerIndices = matrixSnapshot.headerIndices;
+ renderMatrixCellType(cells.at(1), hostname, 'cookie',
+ counts[headerIndices.get('cookie')]);
+ renderMatrixCellType(cells.at(2), hostname, 'css',
+ counts[headerIndices.get('css')]);
+ renderMatrixCellType(cells.at(3), hostname, 'image',
+ counts[headerIndices.get('image')]);
+ renderMatrixCellType(cells.at(4), hostname, 'media',
+ counts[headerIndices.get('media')]);
+ renderMatrixCellType(cells.at(5), hostname, 'script',
+ counts[headerIndices.get('script')]);
+ renderMatrixCellType(cells.at(6), hostname, 'xhr',
+ counts[headerIndices.get('xhr')]);
+ renderMatrixCellType(cells.at(7), hostname, 'frame',
+ counts[headerIndices.get('frame')]);
+ renderMatrixCellType(cells.at(8), hostname, 'other',
+ counts[headerIndices.get('other')]);
}
- /******************************************************************************/
-
function makeMatrixRowDomain(domain) {
- var matrixRow = createMatrixRow().addClass('rw');
- var cells = matrixRow.descendants('.matCell');
+ let matrixRow = createMatrixRow().addClass('rw');
+ let cells = matrixRow.descendants('.matCell');
renderMatrixCellDomain(cells.at(0), domain);
renderMatrixCellTypes(cells, domain, 'counts');
return matrixRow;
}
function makeMatrixRowSubdomain(domain, subdomain) {
- var matrixRow = createMatrixRow().addClass('rw');
- var cells = matrixRow.descendants('.matCell');
+ let matrixRow = createMatrixRow().addClass('rw');
+ let cells = matrixRow.descendants('.matCell');
renderMatrixCellSubdomain(cells.at(0), domain, subdomain);
renderMatrixCellTypes(cells, subdomain, 'counts');
return matrixRow;
}
function makeMatrixMetaRowDomain(domain) {
- var matrixRow = createMatrixRow().addClass('rw');
- var cells = matrixRow.descendants('.matCell');
+ let matrixRow = createMatrixRow().addClass('rw');
+ let cells = matrixRow.descendants('.matCell');
renderMatrixMetaCellDomain(cells.at(0), domain);
renderMatrixCellTypes(cells, domain, 'totals');
return matrixRow;
}
- /******************************************************************************/
-
function renderMatrixMetaCellType(cell, count) {
// https://github.com/gorhill/uMatrix/issues/24
// Don't forget to reset cell properties
- var node = cell.nodeAt(0),
- expandos = expandosFromNode(node);
+ let node = cell.nodeAt(0);
+ let expandos = expandosFromNode(node);
expandos.hostname = '';
expandos.reqType = '';
expandos.count = count;
@@ -748,87 +783,94 @@
}
function makeMatrixMetaRow(totals) {
- var headerIndices = matrixSnapshot.headerIndices,
- matrixRow = createMatrixRow().at(0).addClass('ro'),
- cells = matrixRow.descendants('.matCell'),
- contents = cells.at(0).addClass('t81').contents(),
- expandos = expandosFromNode(cells.nodeAt(0));
+ let headerIndices = matrixSnapshot.headerIndices;
+ let matrixRow = createMatrixRow().at(0).addClass('ro');
+ let cells = matrixRow.descendants('.matCell');
+ let contents = cells.at(0).addClass('t81').contents();
+ let expandos = expandosFromNode(cells.nodeAt(0));
expandos.hostname = '';
expandos.reqType = '*';
contents.nodeAt(0).textContent = ' ';
- contents.nodeAt(1).textContent = blacklistedHostnamesLabel.replace(
- '{{count}}',
- totals[headerIndices.get('*')].toLocaleString()
- );
- renderMatrixMetaCellType(cells.at(1), totals[headerIndices.get('cookie')]);
- renderMatrixMetaCellType(cells.at(2), totals[headerIndices.get('css')]);
- renderMatrixMetaCellType(cells.at(3), totals[headerIndices.get('image')]);
- renderMatrixMetaCellType(cells.at(4), totals[headerIndices.get('media')]);
- renderMatrixMetaCellType(cells.at(5), totals[headerIndices.get('script')]);
- renderMatrixMetaCellType(cells.at(6), totals[headerIndices.get('xhr')]);
- renderMatrixMetaCellType(cells.at(7), totals[headerIndices.get('frame')]);
- renderMatrixMetaCellType(cells.at(8), totals[headerIndices.get('other')]);
+ contents.nodeAt(1).textContent =
+ blacklistedHostnamesLabel
+ .replace('{{count}}',
+ totals[headerIndices.get('*')].toLocaleString());
+
+ renderMatrixMetaCellType(cells.at(1),
+ totals[headerIndices.get('cookie')]);
+ renderMatrixMetaCellType(cells.at(2),
+ totals[headerIndices.get('css')]);
+ renderMatrixMetaCellType(cells.at(3),
+ totals[headerIndices.get('image')]);
+ renderMatrixMetaCellType(cells.at(4),
+ totals[headerIndices.get('media')]);
+ renderMatrixMetaCellType(cells.at(5),
+ totals[headerIndices.get('script')]);
+ renderMatrixMetaCellType(cells.at(6),
+ totals[headerIndices.get('xhr')]);
+ renderMatrixMetaCellType(cells.at(7),
+ totals[headerIndices.get('frame')]);
+ renderMatrixMetaCellType(cells.at(8),
+ totals[headerIndices.get('other')]);
return matrixRow;
}
- /******************************************************************************/
-
function computeMatrixGroupMetaStats(group) {
- var headerIndices = matrixSnapshot.headerIndices,
- anyTypeIndex = headerIndices.get('*'),
- n = headerIndices.size,
- totals = new Array(n),
- i = n;
- while ( i-- ) {
+ let headerIndices = matrixSnapshot.headerIndices;
+ let anyTypeIndex = headerIndices.get('*');
+ let totals = new Array(headerIndices.size);
+
+ for (let i=headerIndices.size-1; i>=0; --i) {
totals[i] = 0;
}
- var rows = matrixSnapshot.rows, row;
- for ( var hostname in rows ) {
- if ( rows.hasOwnProperty(hostname) === false ) {
+
+ let rows = matrixSnapshot.rows;
+ let row;
+ for (let hostname in rows) {
+ if (rows.hasOwnProperty(hostname) === false) {
continue;
}
row = rows[hostname];
- if ( group.hasOwnProperty(row.domain) === false ) {
+ if (group.hasOwnProperty(row.domain) === false) {
continue;
}
- if ( row.counts[anyTypeIndex] === 0 ) {
+ if (row.counts[anyTypeIndex] === 0) {
continue;
}
totals[0] += 1;
- for ( i = 1; i < n; i++ ) {
+ for (let i=1; i<headerIndices.size; ++i) {
totals[i] += row.counts[i];
}
}
+
return totals;
}
- /******************************************************************************/
-
// Compare hostname helper, to order hostname in a logical manner:
// top-most < bottom-most, take into account whether IP address or
// named hostname
- function hostnameCompare(a,b) {
+ function hostnameCompare(a, b) {
// Normalize: most significant parts first
- if ( !a.match(/^\d+(\.\d+){1,3}$/) ) {
- var aa = a.split('.');
+ if (!a.match(/^\d+(\.\d+){1,3}$/)) {
+ let aa = a.split('.');
a = aa.slice(-2).concat(aa.slice(0,-2).reverse()).join('.');
}
- if ( !b.match(/^\d+(\.\d+){1,3}$/) ) {
- var bb = b.split('.');
+
+ if (!b.match(/^\d+(\.\d+){1,3}$/)) {
+ let bb = b.split('.');
b = bb.slice(-2).concat(bb.slice(0,-2).reverse()).join('.');
}
+
return a.localeCompare(b);
}
- /******************************************************************************/
-
function makeMatrixGroup0SectionDomain() {
return makeMatrixRowDomain('1st-party').addClass('g0 l1');
}
function makeMatrixGroup0Section() {
- var domainDiv = createMatrixSection();
+ let domainDiv = createMatrixSection();
expandosFromNode(domainDiv).domain = '1st-party';
makeMatrixGroup0SectionDomain().appendTo(domainDiv);
return domainDiv;
@@ -837,24 +879,20 @@
function makeMatrixGroup0() {
// Show literal "1st-party" row only if there is
// at least one 1st-party hostname
- if ( Object.keys(groupsSnapshot[1]).length === 0 ) {
+ if (Object.keys(groupsSnapshot[1]).length === 0) {
return;
}
- var groupDiv = createMatrixGroup().addClass('g0');
+ let groupDiv = createMatrixGroup().addClass('g0');
makeMatrixGroup0Section().appendTo(groupDiv);
groupDiv.appendTo(matrixList);
}
- /******************************************************************************/
-
function makeMatrixGroup1SectionDomain(domain) {
- return makeMatrixRowDomain(domain)
- .addClass('g1 l1');
+ return makeMatrixRowDomain(domain).addClass('g1 l1');
}
function makeMatrixGroup1SectionSubomain(domain, subdomain) {
- return makeMatrixRowSubdomain(domain, subdomain)
- .addClass('g1 l2');
+ return makeMatrixRowSubdomain(domain, subdomain).addClass('g1 l2');
}
function makeMatrixGroup1SectionMetaDomain(domain) {
@@ -862,17 +900,16 @@
}
function makeMatrixGroup1Section(hostnames) {
- var domain = hostnames[0];
- var domainDiv = createMatrixSection()
- .toggleClass('collapsed', getCollapseState(domain));
+ let domain = hostnames[0];
+ let domainDiv =
+ createMatrixSection().toggleClass('collapsed',
+ getCollapseState(domain));
expandosFromNode(domainDiv).domain = domain;
- if ( hostnames.length > 1 ) {
- makeMatrixGroup1SectionMetaDomain(domain)
- .appendTo(domainDiv);
+ if (hostnames.length > 1) {
+ makeMatrixGroup1SectionMetaDomain(domain).appendTo(domainDiv);
}
- makeMatrixGroup1SectionDomain(domain)
- .appendTo(domainDiv);
- for ( var i = 1; i < hostnames.length; i++ ) {
+ makeMatrixGroup1SectionDomain(domain).appendTo(domainDiv);
+ for (let i=1; i<hostnames.length; ++i) {
makeMatrixGroup1SectionSubomain(domain, hostnames[i])
.appendTo(domainDiv);
}
@@ -880,29 +917,27 @@
}
function makeMatrixGroup1(group) {
- var domains = Object.keys(group).sort(hostnameCompare);
- if ( domains.length ) {
- var groupDiv = createMatrixGroup().addClass('g1');
- makeMatrixGroup1Section(Object.keys(group[domains[0]]).sort(hostnameCompare))
+ let domains = Object.keys(group).sort(hostnameCompare);
+ if (domains.length) {
+ let groupDiv = createMatrixGroup().addClass('g1');
+ makeMatrixGroup1Section(Object.keys(group[domains[0]])
+ .sort(hostnameCompare))
.appendTo(groupDiv);
- for ( var i = 1; i < domains.length; i++ ) {
- makeMatrixGroup1Section(Object.keys(group[domains[i]]).sort(hostnameCompare))
+ for (let i=1; i<domains.length; ++i) {
+ makeMatrixGroup1Section(Object.keys(group[domains[i]])
+ .sort(hostnameCompare))
.appendTo(groupDiv);
}
groupDiv.appendTo(matrixList);
}
}
- /******************************************************************************/
-
function makeMatrixGroup2SectionDomain(domain) {
- return makeMatrixRowDomain(domain)
- .addClass('g2 l1');
+ return makeMatrixRowDomain(domain).addClass('g2 l1');
}
function makeMatrixGroup2SectionSubomain(domain, subdomain) {
- return makeMatrixRowSubdomain(domain, subdomain)
- .addClass('g2 l2');
+ return makeMatrixRowSubdomain(domain, subdomain).addClass('g2 l2');
}
function makeMatrixGroup2SectionMetaDomain(domain) {
@@ -910,16 +945,16 @@
}
function makeMatrixGroup2Section(hostnames) {
- var domain = hostnames[0];
- var domainDiv = createMatrixSection()
- .toggleClass('collapsed', getCollapseState(domain));
+ let domain = hostnames[0];
+ let domainDiv =
+ createMatrixSection().toggleClass('collapsed',
+ getCollapseState(domain));
expandosFromNode(domainDiv).domain = domain;
- if ( hostnames.length > 1 ) {
+ if (hostnames.length > 1) {
makeMatrixGroup2SectionMetaDomain(domain).appendTo(domainDiv);
}
- makeMatrixGroup2SectionDomain(domain)
- .appendTo(domainDiv);
- for ( var i = 1; i < hostnames.length; i++ ) {
+ makeMatrixGroup2SectionDomain(domain).appendTo(domainDiv);
+ for (let i=1; i<hostnames.length; ++i) {
makeMatrixGroup2SectionSubomain(domain, hostnames[i])
.appendTo(domainDiv);
}
@@ -927,30 +962,27 @@
}
function makeMatrixGroup2(group) {
- var domains = Object.keys(group).sort(hostnameCompare);
- if ( domains.length) {
- var groupDiv = createMatrixGroup()
- .addClass('g2');
- makeMatrixGroup2Section(Object.keys(group[domains[0]]).sort(hostnameCompare))
+ let domains = Object.keys(group).sort(hostnameCompare);
+ if (domains.length) {
+ let groupDiv = createMatrixGroup().addClass('g2');
+ makeMatrixGroup2Section(Object.keys(group[domains[0]])
+ .sort(hostnameCompare))
.appendTo(groupDiv);
- for ( var i = 1; i < domains.length; i++ ) {
- makeMatrixGroup2Section(Object.keys(group[domains[i]]).sort(hostnameCompare))
+ for (let i=1; i<domains.length; ++i) {
+ makeMatrixGroup2Section(Object.keys(group[domains[i]])
+ .sort(hostnameCompare))
.appendTo(groupDiv);
}
groupDiv.appendTo(matrixList);
}
}
- /******************************************************************************/
-
function makeMatrixGroup3SectionDomain(domain) {
- return makeMatrixRowDomain(domain)
- .addClass('g3 l1');
+ return makeMatrixRowDomain(domain).addClass('g3 l1');
}
function makeMatrixGroup3SectionSubomain(domain, subdomain) {
- return makeMatrixRowSubdomain(domain, subdomain)
- .addClass('g3 l2');
+ return makeMatrixRowSubdomain(domain, subdomain).addClass('g3 l2');
}
function makeMatrixGroup3SectionMetaDomain(domain) {
@@ -958,16 +990,15 @@
}
function makeMatrixGroup3Section(hostnames) {
- var domain = hostnames[0];
- var domainDiv = createMatrixSection()
- .toggleClass('collapsed', getCollapseState(domain));
+ let domain = hostnames[0];
+ let domainDiv = createMatrixSection().toggleClass('collapsed',
+ getCollapseState(domain));
expandosFromNode(domainDiv).domain = domain;
- if ( hostnames.length > 1 ) {
+ if (hostnames.length > 1) {
makeMatrixGroup3SectionMetaDomain(domain).appendTo(domainDiv);
}
- makeMatrixGroup3SectionDomain(domain)
- .appendTo(domainDiv);
- for ( var i = 1; i < hostnames.length; i++ ) {
+ makeMatrixGroup3SectionDomain(domain).appendTo(domainDiv);
+ for (let i=1; i<hostnames.length; ++i) {
makeMatrixGroup3SectionSubomain(domain, hostnames[i])
.appendTo(domainDiv);
}
@@ -975,39 +1006,35 @@
}
function makeMatrixGroup3(group) {
- var domains = Object.keys(group).sort(hostnameCompare);
- if ( domains.length) {
- var groupDiv = createMatrixGroup()
- .addClass('g3');
- makeMatrixGroup3Section(Object.keys(group[domains[0]]).sort(hostnameCompare))
+ let domains = Object.keys(group).sort(hostnameCompare);
+ if (domains.length) {
+ let groupDiv = createMatrixGroup().addClass('g3');
+ makeMatrixGroup3Section(Object.keys(group[domains[0]])
+ .sort(hostnameCompare))
.appendTo(groupDiv);
- for ( var i = 1; i < domains.length; i++ ) {
- makeMatrixGroup3Section(Object.keys(group[domains[i]]).sort(hostnameCompare))
+ for (let i=1; i<domains.length; ++i) {
+ makeMatrixGroup3Section(Object.keys(group[domains[i]])
+ .sort(hostnameCompare))
.appendTo(groupDiv);
}
groupDiv.appendTo(matrixList);
}
}
- /******************************************************************************/
-
function makeMatrixGroup4SectionDomain(domain) {
- return makeMatrixRowDomain(domain)
- .addClass('g4 l1');
+ return makeMatrixRowDomain(domain).addClass('g4 l1');
}
function makeMatrixGroup4SectionSubomain(domain, subdomain) {
- return makeMatrixRowSubdomain(domain, subdomain)
- .addClass('g4 l2');
+ return makeMatrixRowSubdomain(domain, subdomain).addClass('g4 l2');
}
function makeMatrixGroup4Section(hostnames) {
- var domain = hostnames[0];
- var domainDiv = createMatrixSection();
+ let domain = hostnames[0];
+ let domainDiv = createMatrixSection();
expandosFromNode(domainDiv).domain = domain;
- makeMatrixGroup4SectionDomain(domain)
- .appendTo(domainDiv);
- for ( var i = 1; i < hostnames.length; i++ ) {
+ makeMatrixGroup4SectionDomain(domain).appendTo(domainDiv);
+ for (let i=1; i<hostnames.length; ++i) {
makeMatrixGroup4SectionSubomain(domain, hostnames[i])
.appendTo(domainDiv);
}
@@ -1015,35 +1042,38 @@
}
function makeMatrixGroup4(group) {
- var domains = Object.keys(group).sort(hostnameCompare);
- if ( domains.length === 0 ) {
+ let domains = Object.keys(group).sort(hostnameCompare);
+ if (domains.length === 0) {
return;
}
- var groupDiv = createMatrixGroup().addClass('g4');
+ let groupDiv = createMatrixGroup().addClass('g4');
createMatrixSection()
.addClass('g4Meta')
- .toggleClass('g4Collapsed', !!matrixSnapshot.collapseBlacklistedDomains)
+ .toggleClass('g4Collapsed',
+ !!matrixSnapshot.collapseBlacklistedDomains)
.appendTo(groupDiv);
makeMatrixMetaRow(computeMatrixGroupMetaStats(group), 'g4')
.appendTo(groupDiv);
- makeMatrixGroup4Section(Object.keys(group[domains[0]]).sort(hostnameCompare))
+ makeMatrixGroup4Section(Object.keys(group[domains[0]])
+ .sort(hostnameCompare))
.appendTo(groupDiv);
- for ( var i = 1; i < domains.length; i++ ) {
- makeMatrixGroup4Section(Object.keys(group[domains[i]]).sort(hostnameCompare))
+ for (let i=1; i<domains.length; ++i) {
+ makeMatrixGroup4Section(Object.keys(group[domains[i]])
+ .sort(hostnameCompare))
.appendTo(groupDiv);
}
groupDiv.appendTo(matrixList);
}
- /******************************************************************************/
-
- var makeMenu = function() {
- var groupStats = getGroupStats();
+ let makeMenu = function () {
+ let groupStats = getGroupStats();
- if ( Object.keys(groupStats).length === 0 ) { return; }
+ if (Object.keys(groupStats).length === 0) {
+ return;
+ }
// https://github.com/gorhill/httpswitchboard/issues/31
- if ( matrixCellHotspots ) {
+ if (matrixCellHotspots) {
matrixCellHotspots.detach();
}
@@ -1062,43 +1092,37 @@
resizePopup();
};
- /******************************************************************************/
-
// Do all the stuff that needs to be done before building menu et al.
function initMenuEnvironment() {
- document.body.style.setProperty(
- 'font-size',
- getUserSetting('displayTextSize')
- );
- document.body.classList.toggle(
- 'colorblind',
- getUserSetting('colorBlindFriendly')
- );
- uDom.nodeFromId('version').textContent = matrixSnapshot.appVersion || '';
-
- var prettyNames = matrixHeaderPrettyNames;
- var keys = Object.keys(prettyNames);
- var i = keys.length;
- var cell, key, text;
- while ( i-- ) {
- key = keys[i];
- cell = uDom('#matHead .matCell[data-req-type="'+ key +'"]');
- text = vAPI.i18n(key + 'PrettyName');
+ document.body.style.setProperty('font-size',
+ getUserSetting('displayTextSize'));
+ document.body.classList.toggle('colorblind',
+ getUserSetting('colorBlindFriendly'));
+ uDom.nodeFromId('version').textContent =
+ matrixSnapshot.appVersion || '';
+
+ let prettyNames = matrixHeaderPrettyNames;
+ let keys = Object.keys(prettyNames);
+ for (let i=keys.length-1; i>=0; --i) {
+ let key = keys[i];
+ let cell = uDom('#matHead .matCell[data-req-type="'+ key +'"]');
+ let text = vAPI.i18n(key + 'PrettyName');
cell.text(text);
prettyNames[key] = text;
}
firstPartyLabel = uDom('[data-i18n="matrix1stPartyLabel"]').text();
- blacklistedHostnamesLabel = uDom('[data-i18n="matrixBlacklistedHostnames"]').text();
+ blacklistedHostnamesLabel =
+ uDom('[data-i18n="matrixBlacklistedHostnames"]').text();
}
- /******************************************************************************/
-
// Create page scopes for the web page
function selectGlobalScope() {
- if ( matrixSnapshot.scope === '*' ) { return; }
+ if (matrixSnapshot.scope === '*') {
+ return;
+ }
matrixSnapshot.scope = '*';
document.body.classList.add('globalScope');
matrixSnapshot.tMatrixModifiedTime = undefined;
@@ -1107,8 +1131,10 @@
}
function selectSpecificScope(ev) {
- var newScope = ev.target.getAttribute('data-scope');
- if ( !newScope || matrixSnapshot.scope === newScope ) { return; }
+ let newScope = ev.target.getAttribute('data-scope');
+ if (!newScope || matrixSnapshot.scope === newScope) {
+ return;
+ }
document.body.classList.remove('globalScope');
matrixSnapshot.scope = newScope;
matrixSnapshot.tMatrixModifiedTime = undefined;
@@ -1118,45 +1144,49 @@
function initScopeCell() {
// It's possible there is no page URL at this point: some pages cannot
- // be filtered by uMatrix.
- if ( matrixSnapshot.url === '' ) { return; }
- var specificScope = uDom.nodeFromId('specificScope');
+ // be filtered by ηMatrix.
+ if (matrixSnapshot.url === '') {
+ return;
+ }
+ let specificScope = uDom.nodeFromId('specificScope');
- while ( specificScope.firstChild !== null ) {
+ while (specificScope.firstChild !== null) {
specificScope.removeChild(specificScope.firstChild);
}
// Fill in the scope menu entries
- var pos = matrixSnapshot.domain.indexOf('.');
- var tld, labels;
- if ( pos === -1 ) {
+ let pos = matrixSnapshot.domain.indexOf('.');
+ let tld, labels;
+ if (pos === -1) {
tld = '';
labels = matrixSnapshot.hostname;
} else {
tld = matrixSnapshot.domain.slice(pos + 1);
labels = matrixSnapshot.hostname.slice(0, -tld.length);
}
- var beg = 0, span, label;
- while ( beg < labels.length ) {
+ let beg = 0;
+ let span, label;
+ while (beg < labels.length) {
pos = labels.indexOf('.', beg);
- if ( pos === -1 ) {
+ if (pos === -1) {
pos = labels.length;
} else {
pos += 1;
}
label = document.createElement('span');
- label.appendChild(
- document.createTextNode(punycode.toUnicode(labels.slice(beg, pos)))
- );
+ label.appendChild(document
+ .createTextNode(Punycode
+ .toUnicode(labels.slice(beg,
+ pos))));
span = document.createElement('span');
span.setAttribute('data-scope', labels.slice(beg) + tld);
span.appendChild(label);
specificScope.appendChild(span);
beg = pos;
}
- if ( tld !== '' ) {
+ if (tld !== '') {
label = document.createElement('span');
- label.appendChild(document.createTextNode(punycode.toUnicode(tld)));
+ label.appendChild(document.createTextNode(Punycode.toUnicode(tld)));
span = document.createElement('span');
span.setAttribute('data-scope', tld);
span.appendChild(label);
@@ -1166,50 +1196,48 @@
}
function updateScopeCell() {
- var specificScope = uDom.nodeFromId('specificScope'),
- isGlobal = matrixSnapshot.scope === '*';
+ let specificScope = uDom.nodeFromId('specificScope');
+ let isGlobal = matrixSnapshot.scope === '*';
+
document.body.classList.toggle('globalScope', isGlobal);
specificScope.classList.toggle('on', !isGlobal);
uDom.nodeFromId('globalScope').classList.toggle('on', isGlobal);
- for ( var node of specificScope.children ) {
- node.classList.toggle(
- 'on',
- !isGlobal &&
- matrixSnapshot.scope.endsWith(node.getAttribute('data-scope'))
- );
+
+ for (let node of specificScope.children) {
+ node.classList.toggle('on',
+ !isGlobal
+ && matrixSnapshot
+ .scope
+ .endsWith(node.getAttribute('data-scope')));
}
}
- /******************************************************************************/
-
function updateMatrixSwitches() {
- var count = 0,
- enabled,
- switches = matrixSnapshot.tSwitches;
- for ( var switchName in switches ) {
- if ( switches.hasOwnProperty(switchName) === false ) { continue; }
+ let count = 0;
+ let enabled;
+ let switches = matrixSnapshot.tSwitches;
+
+ for (let switchName in switches) {
+ if (switches.hasOwnProperty(switchName) === false) {
+ continue;
+ }
enabled = switches[switchName];
- if ( enabled && switchName !== 'matrix-off' ) {
+ if (enabled && switchName !== 'matrix-off') {
count += 1;
}
uDom('#mtxSwitch_' + switchName).toggleClass('switchTrue', enabled);
}
- uDom.nodeFromId('mtxSwitch_https-strict').classList.toggle(
- 'relevant',
- matrixSnapshot.hasMixedContent
- );
- uDom.nodeFromId('mtxSwitch_no-workers').classList.toggle(
- 'relevant',
- matrixSnapshot.hasWebWorkers
- );
- uDom.nodeFromId('mtxSwitch_referrer-spoof').classList.toggle(
- 'relevant',
- matrixSnapshot.has3pReferrer
- );
- uDom.nodeFromId('mtxSwitch_noscript-spoof').classList.toggle(
- 'relevant',
- matrixSnapshot.hasNoscriptTags
- );
+ uDom.nodeFromId('mtxSwitch_https-strict')
+ .classList
+ .toggle('relevant', matrixSnapshot.hasMixedContent);
+ uDom.nodeFromId('mtxSwitch_no-workers')
+ .classList
+ .toggle('relevant', matrixSnapshot.hasWebWorkers);
+ uDom.nodeFromId('mtxSwitch_referrer-spoof')
+ .classList.toggle('relevant', matrixSnapshot.has3pReferrer);
+ uDom.nodeFromId('mtxSwitch_noscript-spoof')
+ .classList
+ .toggle('relevant', matrixSnapshot.hasNoscriptTags);
uDom.nodeFromSelector('#buttonMtxSwitches span.badge').textContent =
count.toLocaleString();
uDom.nodeFromSelector('#mtxSwitch_matrix-off span.badge').textContent =
@@ -1218,12 +1246,18 @@
}
function toggleMatrixSwitch(ev) {
- if ( ev.target.localName === 'a' ) { return; }
- var elem = ev.currentTarget;
- var pos = elem.id.indexOf('_');
- if ( pos === -1 ) { return; }
- var switchName = elem.id.slice(pos + 1);
- var request = {
+ if (ev.target.localName === 'a') {
+ return;
+ }
+
+ let elem = ev.currentTarget;
+ let pos = elem.id.indexOf('_');
+ if (pos === -1) {
+ return;
+ }
+
+ let switchName = elem.id.slice(pos + 1);
+ let request = {
what: 'toggleMatrixSwitch',
switchName: switchName,
srcHostname: matrixSnapshot.scope
@@ -1231,46 +1265,44 @@
vAPI.messaging.send('popup.js', request, updateMatrixSnapshot);
}
- /******************************************************************************/
-
function updatePersistButton() {
- var diffCount = matrixSnapshot.diff.length;
- var button = uDom('#buttonPersist');
+ let diffCount = matrixSnapshot.diff.length;
+ let button = uDom('#buttonPersist');
+
button.contents()
- .filter(function(){return this.nodeType===3;})
+ .filter(function () {
+ return this.nodeType===3;
+ })
.first()
.text(diffCount > 0 ? '\uf13e' : '\uf023');
+
button.descendants('span.badge').text(diffCount > 0 ? diffCount : '');
- var disabled = diffCount === 0;
+
+ let disabled = diffCount === 0;
+
button.toggleClass('disabled', disabled);
uDom('#buttonRevertScope').toggleClass('disabled', disabled);
}
- /******************************************************************************/
-
function persistMatrix() {
- var request = {
+ let request = {
what: 'applyDiffToPermanentMatrix',
diff: matrixSnapshot.diff
};
vAPI.messaging.send('popup.js', request, updateMatrixSnapshot);
}
- /******************************************************************************/
-
// rhill 2014-03-12: revert completely ALL changes related to the
// current page, including scopes.
function revertMatrix() {
- var request = {
+ let request = {
what: 'applyDiffToTemporaryMatrix',
diff: matrixSnapshot.diff
};
vAPI.messaging.send('popup.js', request, updateMatrixSnapshot);
}
- /******************************************************************************/
-
// Buttons which are affected by any changes in the matrix
function updateMatrixButtons() {
@@ -1279,18 +1311,14 @@
updatePersistButton();
}
- /******************************************************************************/
-
function revertAll() {
- var request = {
+ let request = {
what: 'revertTemporaryMatrix'
};
vAPI.messaging.send('popup.js', request, updateMatrixSnapshot);
dropDownMenuHide();
}
- /******************************************************************************/
-
function buttonReloadHandler(ev) {
vAPI.messaging.send('popup.js', {
what: 'forceReloadTab',
@@ -1299,8 +1327,6 @@
});
}
- /******************************************************************************/
-
function mouseenterMatrixCellHandler(ev) {
matrixCellHotspots.appendTo(ev.target);
}
@@ -1309,11 +1335,9 @@
matrixCellHotspots.detach();
}
- /******************************************************************************/
-
function gotoExtensionURL(ev) {
- var url = uDom(ev.currentTarget).attr('data-extension-url');
- if ( url ) {
+ let url = uDom(ev.currentTarget).attr('data-extension-url');
+ if (url) {
vAPI.messaging.send('popup.js', {
what: 'gotoExtensionURL',
url: url,
@@ -1324,18 +1348,16 @@
vAPI.closePopup();
}
- /******************************************************************************/
-
function dropDownMenuShow(ev) {
- var button = ev.target;
- var menuOverlay = document.getElementById(button.getAttribute('data-dropdown-menu'));
- var butnRect = button.getBoundingClientRect();
- var viewRect = document.body.getBoundingClientRect();
- var butnNormalLeft = butnRect.left / (viewRect.width - butnRect.width);
+ let button = ev.target;
+ let menuOverlay = document.getElementById(button.getAttribute('data-dropdown-menu'));
+ let butnRect = button.getBoundingClientRect();
+ let viewRect = document.body.getBoundingClientRect();
+ let butnNormalLeft = butnRect.left / (viewRect.width - butnRect.width);
menuOverlay.classList.add('show');
- var menu = menuOverlay.querySelector('.dropdown-menu');
- var menuRect = menu.getBoundingClientRect();
- var menuLeft = butnNormalLeft * (viewRect.width - menuRect.width);
+ let menu = menuOverlay.querySelector('.dropdown-menu');
+ let menuRect = menu.getBoundingClientRect();
+ let menuLeft = butnNormalLeft * (viewRect.width - menuRect.width);
menu.style.left = menuLeft.toFixed(0) + 'px';
menu.style.top = butnRect.bottom + 'px';
}
@@ -1344,10 +1366,8 @@
uDom('.dropdown-menu-capture').removeClass('show');
}
- /******************************************************************************/
-
- var onMatrixSnapshotReady = function(response) {
- if ( response === 'ENOTFOUND' ) {
+ let onMatrixSnapshotReady = function (response) {
+ if (response === 'ENOTFOUND') {
uDom.nodeFromId('noTabFound').textContent =
vAPI.i18n('matrixNoTabFound');
document.body.classList.add('noTabFound');
@@ -1359,7 +1379,7 @@
makeMenu();
// After popup menu is built, check whether there is a non-empty matrix
- if ( matrixSnapshot.url === '' ) {
+ if (matrixSnapshot.url === '') {
uDom('#matHead').remove();
uDom('#toolbarContainer').remove();
@@ -1371,58 +1391,58 @@
// Create a hash to find out whether the reload button needs to be
// highlighted.
// TODO:
+ // ηMatrix: not sure what the purpose of highlighting is...
+ // Maybe telling the user that the page needs refreshing? But
+ // that's hardly useful (and by now people have gotten used to
+ // the lack of such a feature.)
+ // Not really going to do it, but let's leave the comment.
};
- /******************************************************************************/
+ let matrixSnapshotPoller = (function () {
+ let timer = null;
- var matrixSnapshotPoller = (function() {
- var timer = null;
-
- var preprocessMatrixSnapshot = function(snapshot) {
- if ( Array.isArray(snapshot.headerIndices) ) {
+ let preprocessMatrixSnapshot = function (snapshot) {
+ if (Array.isArray(snapshot.headerIndices)) {
snapshot.headerIndices = new Map(snapshot.headerIndices);
}
return snapshot;
};
- var processPollResult = function(response) {
- if ( typeof response !== 'object' ) {
+ let processPollResult = function (response) {
+ if (typeof response !== 'object') {
return;
}
- if (
- response.mtxContentModified === false &&
- response.mtxCountModified === false &&
- response.pMatrixModified === false &&
- response.tMatrixModified === false
- ) {
+
+ if (response.mtxContentModified === false
+ && response.mtxCountModified === false
+ && response.pMatrixModified === false
+ && response.tMatrixModified === false) {
return;
}
matrixSnapshot = preprocessMatrixSnapshot(response);
- if ( response.mtxContentModified ) {
+ if (response.mtxContentModified) {
makeMenu();
return;
}
- if ( response.mtxCountModified ) {
+ if (response.mtxCountModified) {
updateMatrixCounts();
}
- if (
- response.pMatrixModified ||
- response.tMatrixModified ||
- response.scopeModified
- ) {
+ if (response.pMatrixModified
+ || response.tMatrixModified
+ || response.scopeModified) {
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
}
};
- var onPolled = function(response) {
+ let onPolled = function (response) {
processPollResult(response);
pollAsync();
};
- var pollNow = function() {
+ let pollNow = function () {
unpollAsync();
vAPI.messaging.send('popup.js', {
what: 'matrixSnapshot',
@@ -1436,43 +1456,47 @@
}, onPolled);
};
- var poll = function() {
+ let poll = function () {
timer = null;
pollNow();
};
- var pollAsync = function() {
- if ( timer !== null ) {
+ let pollAsync = function () {
+ if (timer !== null) {
return;
}
- if ( document.defaultView === null ) {
+ if (document.defaultView === null) {
return;
}
timer = vAPI.setTimeout(poll, 1414);
};
- var unpollAsync = function() {
- if ( timer !== null ) {
+ let unpollAsync = function () {
+ if (timer !== null) {
clearTimeout(timer);
timer = null;
}
};
- (function() {
- var tabId = matrixSnapshot.tabId;
+ (function () {
+ let tabId = matrixSnapshot.tabId;
// If no tab id yet, see if there is one specified in our URL
- if ( tabId === undefined ) {
- var matches = window.location.search.match(/(?:\?|&)tabId=([^&]+)/);
- if ( matches !== null ) {
+ if (tabId === undefined) {
+ let matches = window
+ .location
+ .search
+ .match(/(?:\?|&)tabId=([^&]+)/);
+
+ if (matches !== null) {
tabId = matches[1];
// No need for logger button when embedded in logger
uDom('[data-extension-url="logger-ui.html"]').remove();
}
}
- var snapshotFetched = function(response) {
- if ( typeof response === 'object' ) {
+ let snapshotFetched = function (response) {
+ if (typeof response === 'object') {
matrixSnapshot = preprocessMatrixSnapshot(response);
}
onMatrixSnapshotReady(response);
@@ -1490,28 +1514,31 @@
};
})();
- /******************************************************************************/
-
// Below is UI stuff which is not key to make the menu, so this can
// be done without having to wait for a tab to be bound to the menu.
// We reuse for all cells the one and only cell hotspots.
- uDom('#whitelist').on('click', function() {
+ uDom('#whitelist').on('click', function () {
handleWhitelistFilter(uDom(this));
return false;
});
- uDom('#blacklist').on('click', function() {
+
+ uDom('#blacklist').on('click', function () {
handleBlacklistFilter(uDom(this));
return false;
});
- uDom('#domainOnly').on('click', function() {
+
+ uDom('#domainOnly').on('click', function () {
toggleCollapseState(uDom(this));
return false;
});
+
matrixCellHotspots = uDom('#cellHotspots').detach();
+
uDom('body')
.on('mouseenter', '.matCell', mouseenterMatrixCellHandler)
.on('mouseleave', '.matCell', mouseleaveMatrixCellHandler);
+
uDom('#specificScope').on('click', selectSpecificScope);
uDom('#globalScope').on('click', selectGlobalScope);
uDom('[id^="mtxSwitch_"]').on('click', toggleMatrixSwitch);
@@ -1525,15 +1552,10 @@
uDom('body').on('click', '[data-dropdown-menu]', dropDownMenuShow);
uDom('body').on('click', '.dropdown-menu-capture', dropDownMenuHide);
- uDom('#matList').on('click', '.g4Meta', function(ev) {
+ uDom('#matList').on('click', '.g4Meta', function (ev) {
matrixSnapshot.collapseBlacklistedDomains =
ev.target.classList.toggle('g4Collapsed');
- setUserSetting(
- 'popupCollapseBlacklistedDomains',
- matrixSnapshot.collapseBlacklistedDomains
- );
+ setUserSetting('popupCollapseBlacklistedDomains',
+ matrixSnapshot.collapseBlacklistedDomains);
});
-
- /******************************************************************************/
-
})();
diff --git a/js/settings.js b/js/settings.js
index da8b6df..8a8d25a 100644
--- a/js/settings.js
+++ b/js/settings.js
@@ -21,19 +21,10 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global uDom */
-
'use strict';
-/******************************************************************************/
-
(function() {
-
- /******************************************************************************/
-
- var cachedSettings = {};
-
- /******************************************************************************/
+ let cachedSettings = {};
function changeUserSettings(name, value) {
vAPI.messaging.send('settings.js', {
@@ -43,8 +34,6 @@
});
}
- /******************************************************************************/
-
function changeMatrixSwitch(name, state) {
vAPI.messaging.send('settings.js', {
what: 'setMatrixSwitch',
@@ -53,69 +42,62 @@
});
}
- /******************************************************************************/
-
function onChangeValueHandler(elem, setting, min, max) {
- var oldVal = cachedSettings.userSettings[setting];
- var newVal = Math.round(parseFloat(elem.value));
- if ( typeof newVal !== 'number' ) {
+ let oldVal = cachedSettings.userSettings[setting];
+ let newVal = Math.round(parseFloat(elem.value));
+ if (typeof newVal !== 'number') {
newVal = oldVal;
} else {
newVal = Math.max(newVal, min);
newVal = Math.min(newVal, max);
}
elem.value = newVal;
- if ( newVal !== oldVal ) {
+ if (newVal !== oldVal) {
changeUserSettings(setting, newVal);
}
}
- /******************************************************************************/
-
function prepareToDie() {
- onChangeValueHandler(
- uDom.nodeFromId('deleteUnusedSessionCookiesAfter'),
- 'deleteUnusedSessionCookiesAfter',
- 15, 1440
- );
- onChangeValueHandler(
- uDom.nodeFromId('clearBrowserCacheAfter'),
- 'clearBrowserCacheAfter',
- 15, 1440
- );
+ onChangeValueHandler(uDom.nodeFromId('deleteUnusedSessionCookiesAfter'),
+ 'deleteUnusedSessionCookiesAfter',
+ 15, 1440);
+ onChangeValueHandler(uDom.nodeFromId('clearBrowserCacheAfter'),
+ 'clearBrowserCacheAfter',
+ 15, 1440);
}
- /******************************************************************************/
-
function onInputChanged(ev) {
- var target = ev.target;
+ let target = ev.target;
- switch ( target.id ) {
+ switch (target.id) {
case 'displayTextSize':
changeUserSettings('displayTextSize', target.value + 'px');
break;
case 'clearBrowserCache':
case 'cloudStorageEnabled':
case 'collapseBlacklisted':
- case 'collapseBlocked':
case 'colorBlindFriendly':
case 'deleteCookies':
case 'deleteLocalStorage':
case 'deleteUnusedSessionCookies':
case 'iconBadgeEnabled':
case 'processHyperlinkAuditing':
+ case 'disableUpdateIcon':
changeUserSettings(target.id, target.checked);
break;
+ case 'collapseBlocked':
+ changeUserSettings(target.id, target.checked);
+ synchronizeWidgets();
+ break;
case 'noMixedContent':
case 'noscriptTagsSpoofed':
case 'processReferer':
- changeMatrixSwitch(
- target.getAttribute('data-matrix-switch'),
- target.checked
- );
+ changeMatrixSwitch(target.getAttribute('data-matrix-switch'),
+ target.checked);
break;
case 'deleteUnusedSessionCookiesAfter':
- onChangeValueHandler(target, 'deleteUnusedSessionCookiesAfter', 15, 1440);
+ onChangeValueHandler(target, 'deleteUnusedSessionCookiesAfter',
+ 15, 1440);
break;
case 'clearBrowserCacheAfter':
onChangeValueHandler(target, 'clearBrowserCacheAfter', 15, 1440);
@@ -126,71 +108,56 @@
default:
break;
}
-
- switch ( target.id ) {
- case 'collapseBlocked':
- synchronizeWidgets();
- break;
- default:
- break;
- }
}
- /******************************************************************************/
-
function synchronizeWidgets() {
- var e1, e2;
+ let e1, e2;
e1 = uDom.nodeFromId('collapseBlocked');
e2 = uDom.nodeFromId('collapseBlacklisted');
- if ( e1.checked ) {
+ if (e1.checked) {
e2.setAttribute('disabled', '');
} else {
e2.removeAttribute('disabled');
}
}
- /******************************************************************************/
+ let onSettingsReceived = function (settings) {
+ // Cache copy
+ cachedSettings = settings;
- vAPI.messaging.send(
- 'settings.js',
- { what: 'getUserSettings' },
- function onSettingsReceived(settings) {
- // Cache copy
- cachedSettings = settings;
+ let userSettings = settings.userSettings;
+ let matrixSwitches = settings.matrixSwitches;
- var userSettings = settings.userSettings;
- var matrixSwitches = settings.matrixSwitches;
-
- uDom('[data-setting-bool]').forEach(function(elem){
- elem.prop('checked', userSettings[elem.prop('id')] === true);
- });
+ uDom('[data-setting-bool]').forEach(function (elem) {
+ elem.prop('checked', userSettings[elem.prop('id')] === true);
+ });
- uDom('[data-matrix-switch]').forEach(function(elem){
- var switchName = elem.attr('data-matrix-switch');
- if ( typeof switchName === 'string' && switchName !== '' ) {
- elem.prop('checked', matrixSwitches[switchName] === true);
- }
- });
+ uDom('[data-matrix-switch]').forEach(function (elem) {
+ let switchName = elem.attr('data-matrix-switch');
+ if (typeof switchName === 'string' && switchName !== '') {
+ elem.prop('checked', matrixSwitches[switchName] === true);
+ }
+ });
- uDom.nodeFromId('displayTextSize').value =
- parseInt(userSettings.displayTextSize, 10) || 14;
+ uDom.nodeFromId('displayTextSize').value =
+ parseInt(userSettings.displayTextSize, 10) || 14;
- uDom.nodeFromId('popupScopeLevel').value = userSettings.popupScopeLevel;
- uDom.nodeFromId('deleteUnusedSessionCookiesAfter').value =
- userSettings.deleteUnusedSessionCookiesAfter;
- uDom.nodeFromId('clearBrowserCacheAfter').value =
- userSettings.clearBrowserCacheAfter;
+ uDom.nodeFromId('popupScopeLevel').value = userSettings.popupScopeLevel;
+ uDom.nodeFromId('deleteUnusedSessionCookiesAfter').value =
+ userSettings.deleteUnusedSessionCookiesAfter;
+ uDom.nodeFromId('clearBrowserCacheAfter').value =
+ userSettings.clearBrowserCacheAfter;
- synchronizeWidgets();
+ synchronizeWidgets();
- document.addEventListener('change', onInputChanged);
+ document.addEventListener('change', onInputChanged);
- // https://github.com/gorhill/httpswitchboard/issues/197
- uDom(window).on('beforeunload', prepareToDie);
- }
- );
-
- /******************************************************************************/
+ // https://github.com/gorhill/httpswitchboard/issues/197
+ uDom(window).on('beforeunload', prepareToDie);
+ }
+ vAPI.messaging.send('settings.js', {
+ what: 'getUserSettings'
+ }, onSettingsReceived);
})();
diff --git a/js/start.js b/js/start.js
index 31a89d8..3a09551 100644
--- a/js/start.js
+++ b/js/start.js
@@ -25,33 +25,25 @@
// ORDER IS IMPORTANT
-/******************************************************************************/
-
// Load everything
(function() {
+ let ηm = ηMatrix;
- /******************************************************************************/
-
- var ηm = ηMatrix;
-
- /******************************************************************************/
-
- var processCallbackQueue = function(queue, callback) {
- var processOne = function() {
- var fn = queue.pop();
- if ( fn ) {
+ let processCallbackQueue = function (queue, callback) {
+ let processOne = function () {
+ let fn = queue.pop();
+ if (fn) {
fn(processOne);
- } else if ( typeof callback === 'function' ) {
+ } else if (typeof callback === 'function') {
callback();
}
};
+
processOne();
};
- /******************************************************************************/
-
- var onAllDone = function() {
+ let onAllDone = function () {
ηm.webRequest.start();
ηm.assets.addObserver(ηm.assetObserver.bind(ηm));
@@ -60,50 +52,38 @@
vAPI.cloud.start([ 'myRulesPane' ]);
};
- /******************************************************************************/
-
- var onTabsReady = function(tabs) {
- var tab;
- var i = tabs.length;
- // console.debug('start.js > binding %d tabs', i);
- while ( i-- ) {
- tab = tabs[i];
+ let onTabsReady = function (tabs) {
+ for (let i=tabs.length-1; i>=0; --i) {
+ // console.debug('start.js > binding %d tabs', i);
+ let tab = tabs[i];
ηm.tabContextManager.push(tab.id, tab.url, 'newURL');
}
onAllDone();
};
- /******************************************************************************/
-
- var onUserSettingsLoaded = function() {
+ let onUserSettingsLoaded = function () {
ηm.loadHostsFiles();
};
- /******************************************************************************/
-
- var onPSLReady = function() {
+ let onPSLReady = function () {
ηm.loadUserSettings(onUserSettingsLoaded);
ηm.loadRawSettings();
ηm.loadMatrix();
- // rhill 2013-11-24: bind behind-the-scene virtual tab/url manually, since the
- // normal way forbid binding behind the scene tab.
+ // rhill 2013-11-24: bind behind-the-scene virtual tab/url
+ // manually, since the normal way forbid binding behind the
+ // scene tab.
// https://github.com/gorhill/httpswitchboard/issues/67
- ηm.pageStores[vAPI.noTabId] = ηm.pageStoreFactory(ηm.tabContextManager.mustLookup(vAPI.noTabId));
- ηm.pageStores[vAPI.noTabId].title = vAPI.i18n('statsPageDetailedBehindTheScenePage');
+ ηm.pageStores[vAPI.noTabId] =
+ ηm.pageStoreFactory(ηm.tabContextManager.mustLookup(vAPI.noTabId));
+ ηm.pageStores[vAPI.noTabId].title =
+ vAPI.i18n('statsPageDetailedBehindTheScenePage');
vAPI.tabs.getAll(onTabsReady);
};
- /******************************************************************************/
-
- processCallbackQueue(ηm.onBeforeStartQueue, function() {
+ processCallbackQueue(ηm.onBeforeStartQueue, function () {
ηm.loadPublicSuffixList(onPSLReady);
});
-
- /******************************************************************************/
-
})();
-
-/******************************************************************************/
diff --git a/js/storage.js b/js/storage.js
index b3a5e7b..012d2f2 100644
--- a/js/storage.js
+++ b/js/storage.js
@@ -21,10 +21,12 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global objectAssign, punycode, publicSuffixList */
+/* global objectAssign, publicSuffixList */
'use strict';
+Components.utils.import('chrome://ematrix/content/lib/PublicSuffixList.jsm');
+
/******************************************************************************/
ηMatrix.getBytesInUse = function() {
@@ -264,7 +266,7 @@
if ( entries.hasOwnProperty(assetKey) === false ) { continue; }
entry = entries[assetKey];
if ( entry.content !== 'filters' ) { continue; }
- availableHostsFiles[assetKey] = objectAssign({}, entry);
+ availableHostsFiles[assetKey] = Object.assign({}, entry);
}
// Now get user's selection of lists
@@ -517,7 +519,7 @@
var applyPublicSuffixList = function(details) {
if ( !details.error ) {
- publicSuffixList.parse(details.content, punycode.toASCII);
+ publicSuffixList.parse(details.content, Punycode.toASCII);
}
callback();
};
diff --git a/js/tab.js b/js/tab.js
index abaaf07..b34d923 100644
--- a/js/tab.js
+++ b/js/tab.js
@@ -21,32 +21,26 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/******************************************************************************/
-/******************************************************************************/
-
-(function() {
-
+(function () {
'use strict';
- /******************************************************************************/
+ Cu.import('chrome://ematrix/content/lib/UriTools.jsm');
var ηm = ηMatrix;
// https://github.com/gorhill/httpswitchboard/issues/303
// Some kind of trick going on here:
- // Any scheme other than 'http' and 'https' is remapped into a fake
- // URL which trick the rest of ηMatrix into being able to process an
- // otherwise unmanageable scheme. ηMatrix needs web page to have a proper
- // hostname to work properly, so just like the 'behind-the-scene'
- // fake domain name, we map unknown schemes into a fake '{scheme}-scheme'
- // hostname. This way, for a specific scheme you can create scope with
- // rules which will apply only to that scheme.
-
- /******************************************************************************/
- /******************************************************************************/
-
- ηm.normalizePageURL = function(tabId, pageURL) {
- if ( vAPI.isBehindTheSceneTabId(tabId) ) {
+ // Any scheme other than 'http' and 'https' is remapped into a
+ // fake URL which trick the rest of ηMatrix into being able to
+ // process an otherwise unmanageable scheme. ηMatrix needs web
+ // page to have a proper hostname to work properly, so just like
+ // the 'behind-the-scene' fake domain name, we map unknown
+ // schemes into a fake '{scheme}-scheme' hostname. This way, for
+ // a specific scheme you can create scope with rules which will
+ // apply only to that scheme.
+
+ ηm.normalizePageURL = function (tabId, pageURL) {
+ if (vAPI.isBehindTheSceneTabId(tabId)) {
return 'http://' + this.behindTheSceneScope + '/';
}
@@ -59,117 +53,122 @@
}
}
- // If the URL is that of our "blocked page" document, return the URL of
- // the blocked page.
- if ( pageURL.lastIndexOf(vAPI.getURL('main-blocked.html'), 0) === 0 ) {
- var matches = /main-blocked\.html\?details=([^&]+)/.exec(pageURL);
- if ( matches && matches.length === 2 ) {
+ // If the URL is that of our "blocked page" document, return
+ // the URL of the blocked page.
+ if (pageURL.lastIndexOf(vAPI.getURL('main-blocked.html'), 0) === 0) {
+ let matches = /main-blocked\.html\?details=([^&]+)/.exec(pageURL);
+ if (matches && matches.length === 2) {
try {
- var details = JSON.parse(atob(matches[1]));
+ let details = JSON.parse(atob(matches[1]));
pageURL = details.url;
} catch (e) {
}
}
}
- var uri = this.URI.set(pageURL);
- var scheme = uri.scheme;
- if ( scheme === 'https' || scheme === 'http' ) {
- return uri.normalizedURI();
+ let uri = UriTools.set(pageURL);
+ let scheme = uri.scheme;
+ if (scheme === 'https' || scheme === 'http') {
+ return UriTools.normalizedURI();
}
- var fakeHostname = scheme + '-scheme';
+ let fakeHostname = scheme + '-scheme';
- if ( uri.hostname !== '' ) {
+ if (uri.hostname !== '') {
fakeHostname = uri.hostname + '.' + fakeHostname;
- } else if ( scheme === 'about' ) {
+ } else if (scheme === 'about') {
fakeHostname = uri.path + '.' + fakeHostname;
}
return 'http://' + fakeHostname + '/';
};
- /******************************************************************************/
- /******************************************************************************
-
-To keep track from which context *exactly* network requests are made. This is
-often tricky for various reasons, and the challenge is not specific to one
-browser.
-
-The time at which a URL is assigned to a tab and the time when a network
-request for a root document is made must be assumed to be unrelated: it's all
-asynchronous. There is no guaranteed order in which the two events are fired.
-
-Also, other "anomalies" can occur:
-
-- a network request for a root document is fired without the corresponding
-tab being really assigned a new URL
-<https://github.com/chrisaljoudi/uBlock/issues/516>
-
-- a network request for a secondary resource is labeled with a tab id for
-which no root document was pulled for that tab.
-<https://github.com/chrisaljoudi/uBlock/issues/1001>
-
-- a network request for a secondary resource is made without the root
-document to which it belongs being formally bound yet to the proper tab id,
-causing a bad scope to be used for filtering purpose.
-<https://github.com/chrisaljoudi/uBlock/issues/1205>
-<https://github.com/chrisaljoudi/uBlock/issues/1140>
-
-So the solution here is to keep a lightweight data structure which only
-purpose is to keep track as accurately as possible of which root document
-belongs to which tab. That's the only purpose, and because of this, there are
-no restrictions for when the URL of a root document can be associated to a tab.
-
-Before, the PageStore object was trying to deal with this, but it had to
-enforce some restrictions so as to not descend into one of the above issues, or
-other issues. The PageStore object can only be associated with a tab for which
-a definitive navigation event occurred, because it collects information about
-what occurred in the tab (for example, the number of requests blocked for a
-page).
-
-The TabContext objects do not suffer this restriction, and as a result they
-offer the most reliable picture of which root document URL is really associated
-to which tab. Moreover, the TabObject can undo an association from a root
-document, and automatically re-associate with the next most recent. This takes
-care of <https://github.com/chrisaljoudi/uBlock/issues/516>.
-
-The PageStore object no longer cache the various information about which
-root document it is currently bound. When it needs to find out, it will always
-defer to the TabContext object, which will provide the real answer. This takes
-case of <https://github.com/chrisaljoudi/uBlock/issues/1205>. In effect, the
-master switch and dynamic filtering rules can be evaluated now properly even
-in the absence of a PageStore object, this was not the case before.
-
-Also, the TabContext object will try its best to find a good candidate root
-document URL for when none exists. This takes care of
-<https://github.com/chrisaljoudi/uBlock/issues/1001>.
-
-The TabContext manager is self-contained, and it takes care to properly
-housekeep itself.
-
+ /*
+ To keep track from which context *exactly* network requests are
+ made. This is often tricky for various reasons, and the
+ challenge is not specific to one browser.
+
+ The time at which a URL is assigned to a tab and the time when a
+ network request for a root document is made must be assumed to
+ be unrelated: it's all asynchronous. There is no guaranteed
+ order in which the two events are fired.
+
+ Also, other "anomalies" can occur:
+
+ - a network request for a root document is fired without the
+ corresponding tab being really assigned a new URL.
+ <https://github.com/chrisaljoudi/uBlock/issues/516>
+
+ - a network request for a secondary resource is labeled with a
+ tab id for which no root document was pulled for that tab.
+ <https://github.com/chrisaljoudi/uBlock/issues/1001>
+
+ - a network request for a secondary resource is made without the
+ root document to which it belongs being formally bound yet to
+ the proper tab id, causing a bad scope to be used for filtering
+ purpose.
+ <https://github.com/chrisaljoudi/uBlock/issues/1205>
+ <https://github.com/chrisaljoudi/uBlock/issues/1140>
+
+ So the solution here is to keep a lightweight data structure
+ which only purpose is to keep track as accurately as possible of
+ which root document belongs to which tab. That's the only
+ purpose, and because of this, there are no restrictions for when
+ the URL of a root document can be associated to a tab.
+
+ Before, the PageStore object was trying to deal with this, but
+ it had to enforce some restrictions so as to not descend into
+ one of the above issues, or other issues. The PageStore object
+ can only be associated with a tab for which a definitive
+ navigation event occurred, because it collects information about
+ what occurred in the tab (for example, the number of requests
+ blocked for a page).
+
+ The TabContext objects do not suffer this restriction, and as a
+ result they offer the most reliable picture of which root
+ document URL is really associated to which tab. Moreover, the
+ TabObject can undo an association from a root document, and
+ automatically re-associate with the next most recent. This takes
+ care of <https://github.com/chrisaljoudi/uBlock/issues/516>.
+
+ The PageStore object no longer cache the various information
+ about which root document it is currently bound. When it needs
+ to find out, it will always defer to the TabContext object,
+ which will provide the real answer. This takes case of
+ <https://github.com/chrisaljoudi/uBlock/issues/1205>. In effect,
+ the master switch and dynamic filtering rules can be evaluated
+ now properly even in the absence of a PageStore object, this was
+ not the case before.
+
+ Also, the TabContext object will try its best to find a good
+ candidate root document URL for when none exists. This takes
+ care of <https://github.com/chrisaljoudi/uBlock/issues/1001>.
+
+ The TabContext manager is self-contained, and it takes care to
+ properly housekeep itself.
*/
- ηm.tabContextManager = (function() {
- var tabContexts = Object.create(null);
+ ηm.tabContextManager = (function () {
+ let tabContexts = Object.create(null);
// https://github.com/chrisaljoudi/uBlock/issues/1001
- // This is to be used as last-resort fallback in case a tab is found to not
- // be bound while network requests are fired for the tab.
- var mostRecentRootDocURL = '';
- var mostRecentRootDocURLTimestamp = 0;
+ // This is to be used as last-resort fallback in case a tab is
+ // found to not be bound while network requests are fired for
+ // the tab.
+ let mostRecentRootDocURL = '';
+ let mostRecentRootDocURLTimestamp = 0;
- var gcPeriod = 31 * 60 * 1000; // every 31 minutes
+ let gcPeriod = 31 * 60 * 1000; // every 31 minutes
- // A pushed entry is removed from the stack unless it is committed with
- // a set time.
- var StackEntry = function(url, commit) {
+ // A pushed entry is removed from the stack unless it is
+ // committed with a set time.
+ let StackEntry = function (url, commit) {
this.url = url;
this.committed = commit;
this.tstamp = Date.now();
};
- var TabContext = function(tabId) {
+ let TabContext = function (tabId) {
this.tabId = tabId;
this.stack = [];
this.rawURL =
@@ -184,120 +183,134 @@ housekeep itself.
tabContexts[tabId] = this;
};
- TabContext.prototype.destroy = function() {
- if ( vAPI.isBehindTheSceneTabId(this.tabId) ) {
+ TabContext.prototype.destroy = function () {
+ if (vAPI.isBehindTheSceneTabId(this.tabId)) {
return;
}
- if ( this.gcTimer !== null ) {
+ if (this.gcTimer !== null) {
clearTimeout(this.gcTimer);
this.gcTimer = null;
}
delete tabContexts[this.tabId];
};
- TabContext.prototype.onTab = function(tab) {
- if ( tab ) {
+ TabContext.prototype.onTab = function (tab) {
+ if (tab) {
this.gcTimer = vAPI.setTimeout(this.onGC.bind(this), gcPeriod);
} else {
this.destroy();
}
};
- TabContext.prototype.onGC = function() {
+ TabContext.prototype.onGC = function () {
this.gcTimer = null;
- if ( vAPI.isBehindTheSceneTabId(this.tabId) ) {
+ if (vAPI.isBehindTheSceneTabId(this.tabId)) {
return;
}
vAPI.tabs.get(this.tabId, this.onTab.bind(this));
};
// https://github.com/gorhill/uBlock/issues/248
- // Stack entries have to be committed to stick. Non-committed stack
- // entries are removed after a set delay.
- TabContext.prototype.onCommit = function() {
- if ( vAPI.isBehindTheSceneTabId(this.tabId) ) {
+ // Stack entries have to be committed to stick. Non-committed
+ // stack entries are removed after a set delay.
+ TabContext.prototype.onCommit = function () {
+ if (vAPI.isBehindTheSceneTabId(this.tabId)) {
return;
}
this.commitTimer = null;
// Remove uncommitted entries at the top of the stack.
- var i = this.stack.length;
- while ( i-- ) {
- if ( this.stack[i].committed ) {
+ let i = this.stack.length;
+ while (i--) {
+ if (this.stack[i].committed) {
break;
}
}
// https://github.com/gorhill/uBlock/issues/300
// If no committed entry was found, fall back on the bottom-most one
// as being the committed one by default.
- if ( i === -1 && this.stack.length !== 0 ) {
+ if (i === -1 && this.stack.length !== 0) {
this.stack[0].committed = true;
i = 0;
}
- i += 1;
- if ( i < this.stack.length ) {
+
+ ++i;
+ if (i < this.stack.length) {
this.stack.length = i;
this.update();
ηm.bindTabToPageStats(this.tabId, 'newURL');
}
};
- // This takes care of orphanized tab contexts. Can't be started for all
- // contexts, as the behind-the-scene context is permanent -- so we do not
- // want to flush it.
- TabContext.prototype.autodestroy = function() {
- if ( vAPI.isBehindTheSceneTabId(this.tabId) ) {
+ // This takes care of orphanized tab contexts. Can't be
+ // started for all contexts, as the behind-the-scene context
+ // is permanent -- so we do not want to flush it.
+ TabContext.prototype.autodestroy = function () {
+ if (vAPI.isBehindTheSceneTabId(this.tabId)) {
return;
}
this.gcTimer = vAPI.setTimeout(this.onGC.bind(this), gcPeriod);
};
- // Update just force all properties to be updated to match the most recent
- // root URL.
- TabContext.prototype.update = function() {
- if ( this.stack.length === 0 ) {
- this.rawURL = this.normalURL = this.scheme =
- this.rootHostname = this.rootDomain = '';
+ // Update just force all properties to be updated to match the
+ // most recent root URL.
+ TabContext.prototype.update = function () {
+ if (this.stack.length === 0) {
+ this.rawURL =
+ this.normalURL =
+ this.scheme =
+ this.rootHostname =
+ this.rootDomain = '';
this.secure = false;
return;
}
+
this.rawURL = this.stack[this.stack.length - 1].url;
this.normalURL = ηm.normalizePageURL(this.tabId, this.rawURL);
- this.scheme = ηm.URI.schemeFromURI(this.rawURL);
- this.rootHostname = ηm.URI.hostnameFromURI(this.normalURL);
- this.rootDomain = ηm.URI.domainFromHostname(this.rootHostname) || this.rootHostname;
- this.secure = ηm.URI.isSecureScheme(this.scheme);
+ this.scheme = UriTools.schemeFromURI(this.rawURL);
+ this.rootHostname = UriTools.hostnameFromURI(this.normalURL);
+ this.rootDomain = UriTools.domainFromHostname(this.rootHostname)
+ || this.rootHostname;
+ this.secure = UriTools.isSecureScheme(this.scheme);
};
// Called whenever a candidate root URL is spotted for the tab.
- TabContext.prototype.push = function(url, context) {
- if ( vAPI.isBehindTheSceneTabId(this.tabId) ) { return; }
- var committed = context !== undefined;
- var count = this.stack.length;
- var topEntry = this.stack[count - 1];
- if ( topEntry && topEntry.url === url ) {
- if ( committed ) {
+ TabContext.prototype.push = function (url, context) {
+ if (vAPI.isBehindTheSceneTabId(this.tabId)) {
+ return;
+ }
+
+ let committed = context !== undefined;
+ let count = this.stack.length;
+ let topEntry = this.stack[count - 1];
+
+ if (topEntry && topEntry.url === url) {
+ if (committed) {
topEntry.committed = true;
}
return;
}
- if ( this.commitTimer !== null ) {
+
+ if (this.commitTimer !== null) {
clearTimeout(this.commitTimer);
}
- if ( committed ) {
+
+ if (committed) {
this.stack = [new StackEntry(url, true)];
} else {
this.stack.push(new StackEntry(url));
- this.commitTimer = vAPI.setTimeout(this.onCommit.bind(this), 1000);
+ this.commitTimer =
+ vAPI.setTimeout(this.onCommit.bind(this), 1000);
}
+
this.update();
ηm.bindTabToPageStats(this.tabId, context);
};
// These are to be used for the API of the tab context manager.
- var push = function(tabId, url, context) {
- var entry = tabContexts[tabId];
- if ( entry === undefined ) {
+ let push = function (tabId, url, context) {
+ let entry = tabContexts[tabId];
+ if (entry === undefined) {
entry = new TabContext(tabId);
entry.autodestroy();
}
@@ -307,64 +320,77 @@ housekeep itself.
return entry;
};
- // Find a tab context for a specific tab. If none is found, attempt to
- // fix this. When all fail, the behind-the-scene context is returned.
- var mustLookup = function(tabId, url) {
- var entry;
- if ( url !== undefined ) {
+ // Find a tab context for a specific tab. If none is found,
+ // attempt to fix this. When all fail, the behind-the-scene
+ // context is returned.
+ let mustLookup = function (tabId, url) {
+ let entry;
+
+ if (url !== undefined) {
entry = push(tabId, url);
} else {
entry = tabContexts[tabId];
}
- if ( entry !== undefined ) {
+
+ if (entry !== undefined) {
return entry;
}
+
// https://github.com/chrisaljoudi/uBlock/issues/1025
- // Google Hangout popup opens without a root frame. So for now we will
- // just discard that best-guess root frame if it is too far in the
- // future, at which point it ceases to be a "best guess".
- if ( mostRecentRootDocURL !== '' && mostRecentRootDocURLTimestamp + 500 < Date.now() ) {
+ // Google Hangout popup opens without a root frame. So for
+ // now we will just discard that best-guess root frame if
+ // it is too far in the future, at which point it ceases
+ // to be a "best guess".
+ if (mostRecentRootDocURL
+ !== '' && mostRecentRootDocURLTimestamp + 500 < Date.now()) {
mostRecentRootDocURL = '';
}
+
// https://github.com/chrisaljoudi/uBlock/issues/1001
- // Not a behind-the-scene request, yet no page store found for the
- // tab id: we will thus bind the last-seen root document to the
- // unbound tab. It's a guess, but better than ending up filtering
- // nothing at all.
- if ( mostRecentRootDocURL !== '' ) {
+ // Not a behind-the-scene request, yet no page store found
+ // for the tab id: we will thus bind the last-seen root
+ // document to the unbound tab. It's a guess, but better
+ // than ending up filtering nothing at all.
+ if (mostRecentRootDocURL !== '') {
return push(tabId, mostRecentRootDocURL);
}
- // If all else fail at finding a page store, re-categorize the
- // request as behind-the-scene. At least this ensures that ultimately
- // the user can still inspect/filter those net requests which were
- // about to fall through the cracks.
+
+ // If all else fail at finding a page store, re-categorize
+ // the request as behind-the-scene. At least this ensures
+ // that ultimately the user can still inspect/filter those
+ // net requests which were about to fall through the
+ // cracks.
// Example: Chromium + case #12 at
// http://raymondhill.net/ublock/popup.html
return tabContexts[vAPI.noTabId];
};
- var lookup = function(tabId) {
+ let lookup = function (tabId) {
return tabContexts[tabId] || null;
};
// Behind-the-scene tab context
- (function() {
- var entry = new TabContext(vAPI.noTabId);
+ (function () {
+ let entry = new TabContext(vAPI.noTabId);
entry.stack.push(new StackEntry('', true));
entry.rawURL = '';
entry.normalURL = ηm.normalizePageURL(entry.tabId);
- entry.rootHostname = ηm.URI.hostnameFromURI(entry.normalURL);
- entry.rootDomain = ηm.URI.domainFromHostname(entry.rootHostname) || entry.rootHostname;
+ entry.rootHostname = UriTools.hostnameFromURI(entry.normalURL);
+ entry.rootDomain = UriTools.domainFromHostname(entry.rootHostname)
+ || entry.rootHostname;
})();
// https://github.com/gorhill/uMatrix/issues/513
- // Force a badge update here, it could happen that all the subsequent
- // network requests are already in the page store, which would cause
- // the badge to no be updated for these network requests.
-
- vAPI.tabs.onNavigation = function(details) {
- var tabId = details.tabId;
- if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
+ // Force a badge update here, it could happen that all the
+ // subsequent network requests are already in the page
+ // store, which would cause the badge to no be updated for
+ // these network requests.
+
+ vAPI.tabs.onNavigation = function (details) {
+ let tabId = details.tabId;
+ if (vAPI.isBehindTheSceneTabId(tabId)) {
+ return;
+ }
push(tabId, details.url, 'newURL');
ηm.updateBadgeAsync(tabId);
};
@@ -372,19 +398,25 @@ housekeep itself.
// https://github.com/gorhill/uMatrix/issues/872
// `changeInfo.url` may not always be available (Firefox).
- vAPI.tabs.onUpdated = function(tabId, changeInfo, tab) {
- if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
- if ( typeof tab.url !== 'string' || tab.url === '' ) { return; }
- var url = changeInfo.url || tab.url;
- if ( url ) {
+ vAPI.tabs.onUpdated = function (tabId, changeInfo, tab) {
+ if (vAPI.isBehindTheSceneTabId(tabId)) {
+ return;
+ }
+
+ if (typeof tab.url !== 'string' || tab.url === '') {
+ return;
+ }
+
+ let url = changeInfo.url || tab.url;
+ if (url) {
push(tabId, url, 'updateURL');
}
};
- vAPI.tabs.onClosed = function(tabId) {
+ vAPI.tabs.onClosed = function (tabId) {
ηm.unbindTabFromPageStats(tabId);
- var entry = tabContexts[tabId];
- if ( entry instanceof TabContext ) {
+ let entry = tabContexts[tabId];
+ if (entry instanceof TabContext) {
entry.destroy();
}
};
@@ -398,45 +430,43 @@ housekeep itself.
vAPI.tabs.registerListeners();
- /******************************************************************************/
- /******************************************************************************/
-
// Create an entry for the tab if it doesn't exist
- ηm.bindTabToPageStats = function(tabId, context) {
+ ηm.bindTabToPageStats = function (tabId, context) {
this.updateBadgeAsync(tabId);
- // Do not create a page store for URLs which are of no interests
- // Example: dev console
- var tabContext = this.tabContextManager.lookup(tabId);
- if ( tabContext === null ) {
+ // Do not create a page store for URLs which are of no
+ // interests Example: dev console
+ let tabContext = this.tabContextManager.lookup(tabId);
+ if (tabContext === null) {
throw new Error('Unmanaged tab id: ' + tabId);
}
// rhill 2013-11-24: Never ever rebind behind-the-scene
// virtual tab.
// https://github.com/gorhill/httpswitchboard/issues/67
- if ( vAPI.isBehindTheSceneTabId(tabId) ) {
+ if (vAPI.isBehindTheSceneTabId(tabId)) {
return this.pageStores[tabId];
}
- var normalURL = tabContext.normalURL;
- var pageStore = this.pageStores[tabId] || null;
+ let normalURL = tabContext.normalURL;
+ let pageStore = this.pageStores[tabId] || null;
// The previous page URL, if any, associated with the tab
- if ( pageStore !== null ) {
+ if (pageStore !== null) {
// No change, do not rebind
- if ( pageStore.pageUrl === normalURL ) {
+ if (pageStore.pageUrl === normalURL) {
return pageStore;
}
// https://github.com/gorhill/uMatrix/issues/37
- // Just rebind whenever possible: the URL changed, but the document
- // maybe is the same.
+ // Just rebind whenever possible: the URL changed, but the
+ // document maybe is the same.
// Example: Google Maps, Github
// https://github.com/gorhill/uMatrix/issues/72
// Need to double-check that the new scope is same as old scope
- if ( context === 'updateURL' && pageStore.pageHostname === tabContext.rootHostname ) {
+ if (context === 'updateURL'
+ && pageStore.pageHostname === tabContext.rootHostname) {
pageStore.rawURL = tabContext.rawURL;
pageStore.normalURL = normalURL;
this.updateTitle(tabId);
@@ -450,259 +480,266 @@ housekeep itself.
// Try to resurrect first.
pageStore = this.resurrectPageStore(tabId, normalURL);
- if ( pageStore === null ) {
+ if (pageStore === null) {
pageStore = this.pageStoreFactory(tabContext);
}
this.pageStores[tabId] = pageStore;
this.updateTitle(tabId);
this.pageStoresToken = Date.now();
- // console.debug('tab.js > bindTabToPageStats(): dispatching traffic in tab id %d to page store "%s"', tabId, pageUrl);
-
return pageStore;
};
- /******************************************************************************/
-
- ηm.unbindTabFromPageStats = function(tabId) {
- // Never unbind behind-the-scene page store.
- if ( vAPI.isBehindTheSceneTabId(tabId) ) {
+ ηm.unbindTabFromPageStats = function (tabId) {
+ if (vAPI.isBehindTheSceneTabId(tabId)) {
return;
}
- var pageStore = this.pageStores[tabId] || null;
- if ( pageStore === null ) {
+ let pageStore = this.pageStores[tabId] || null;
+ if (pageStore === null) {
return;
}
delete this.pageStores[tabId];
this.pageStoresToken = Date.now();
- if ( pageStore.incinerationTimer ) {
+ if (pageStore.incinerationTimer) {
clearTimeout(pageStore.incinerationTimer);
pageStore.incinerationTimer = null;
}
- if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) {
+ if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) {
this.pageStoreCemetery[tabId] = {};
}
- var pageStoreCrypt = this.pageStoreCemetery[tabId];
+ let pageStoreCrypt = this.pageStoreCemetery[tabId];
- var pageURL = pageStore.pageUrl;
+ let pageURL = pageStore.pageUrl;
pageStoreCrypt[pageURL] = pageStore;
- pageStore.incinerationTimer = vAPI.setTimeout(
- this.incineratePageStore.bind(this, tabId, pageURL),
- 4 * 60 * 1000
- );
+ pageStore.incinerationTimer =
+ vAPI.setTimeout(this.incineratePageStore.bind(this, tabId, pageURL),
+ 4 * 60 * 1000);
};
- /******************************************************************************/
-
- ηm.resurrectPageStore = function(tabId, pageURL) {
- if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) {
+ ηm.resurrectPageStore = function (tabId, pageURL) {
+ if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) {
return null;
}
- var pageStoreCrypt = this.pageStoreCemetery[tabId];
- if ( pageStoreCrypt.hasOwnProperty(pageURL) === false ) {
+ let pageStoreCrypt = this.pageStoreCemetery[tabId];
+
+ if (pageStoreCrypt.hasOwnProperty(pageURL) === false) {
return null;
}
- var pageStore = pageStoreCrypt[pageURL];
+ let pageStore = pageStoreCrypt[pageURL];
- if ( pageStore.incinerationTimer !== null ) {
+ if (pageStore.incinerationTimer !== null) {
clearTimeout(pageStore.incinerationTimer);
pageStore.incinerationTimer = null;
}
delete pageStoreCrypt[pageURL];
- if ( Object.keys(pageStoreCrypt).length === 0 ) {
+ if (Object.keys(pageStoreCrypt).length === 0) {
delete this.pageStoreCemetery[tabId];
}
return pageStore;
};
- /******************************************************************************/
-
- ηm.incineratePageStore = function(tabId, pageURL) {
- if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) {
+ ηm.incineratePageStore = function (tabId, pageURL) {
+ if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) {
return;
}
- var pageStoreCrypt = this.pageStoreCemetery[tabId];
- if ( pageStoreCrypt.hasOwnProperty(pageURL) === false ) {
+ let pageStoreCrypt = this.pageStoreCemetery[tabId];
+
+ if (pageStoreCrypt.hasOwnProperty(pageURL) === false) {
return;
}
- var pageStore = pageStoreCrypt[pageURL];
- if ( pageStore.incinerationTimer !== null ) {
+ let pageStore = pageStoreCrypt[pageURL];
+ if (pageStore.incinerationTimer !== null) {
clearTimeout(pageStore.incinerationTimer);
pageStore.incinerationTimer = null;
}
delete pageStoreCrypt[pageURL];
- if ( Object.keys(pageStoreCrypt).length === 0 ) {
+
+ if (Object.keys(pageStoreCrypt).length === 0) {
delete this.pageStoreCemetery[tabId];
}
pageStore.dispose();
};
- /******************************************************************************/
-
- ηm.pageStoreFromTabId = function(tabId) {
+ ηm.pageStoreFromTabId = function (tabId) {
return this.pageStores[tabId] || null;
};
// Never return null
- ηm.mustPageStoreFromTabId = function(tabId) {
+ ηm.mustPageStoreFromTabId = function (tabId) {
return this.pageStores[tabId] || this.pageStores[vAPI.noTabId];
};
- /******************************************************************************/
-
- ηm.forceReload = function(tabId, bypassCache) {
+ ηm.forceReload = function (tabId, bypassCache) {
vAPI.tabs.reload(tabId, bypassCache);
};
- /******************************************************************************/
-
// Update badge
// rhill 2013-11-09: well this sucks, I can't update icon/badge
- // incrementally, as chromium overwrite the icon at some point without
- // notifying me, and this causes internal cached state to be out of sync.
+ // incrementally, as chromium overwrite the icon at some point
+ // without notifying me, and this causes internal cached state to
+ // be out of sync.
+ // ηMatrix: does it matter to us?
- ηm.updateBadgeAsync = (function() {
- var tabIdToTimer = Object.create(null);
+ ηm.updateBadgeAsync = (function () {
+ let tabIdToTimer = Object.create(null);
- var updateBadge = function(tabId) {
+ let updateBadge = function (tabId) {
delete tabIdToTimer[tabId];
- var iconId = null;
- var badgeStr = '';
+ let iconId = null;
+ let badgeStr = '';
- var pageStore = this.pageStoreFromTabId(tabId);
- if ( pageStore !== null ) {
- var total = pageStore.perLoadAllowedRequestCount +
+ let pageStore = this.pageStoreFromTabId(tabId);
+ if (pageStore !== null) {
+ let total = pageStore.perLoadAllowedRequestCount +
pageStore.perLoadBlockedRequestCount;
- if ( total ) {
- var squareSize = 19;
- var greenSize = squareSize * Math.sqrt(pageStore.perLoadAllowedRequestCount / total);
- iconId = greenSize < squareSize/2 ? Math.ceil(greenSize) : Math.floor(greenSize);
+
+ if (total) {
+ let squareSize = 19;
+ let greenSize = squareSize *
+ Math.sqrt(pageStore.perLoadAllowedRequestCount / total);
+
+ iconId = greenSize < squareSize/2 ?
+ Math.ceil(greenSize) :
+ Math.floor(greenSize);
}
- if ( this.userSettings.iconBadgeEnabled && pageStore.perLoadBlockedRequestCount !== 0) {
- badgeStr = this.formatCount(pageStore.perLoadBlockedRequestCount);
+
+ if (this.userSettings.iconBadgeEnabled
+ && pageStore.perLoadBlockedRequestCount !== 0) {
+ badgeStr =
+ this.formatCount(pageStore.perLoadBlockedRequestCount);
}
}
vAPI.setIcon(tabId, iconId, badgeStr);
};
- return function(tabId) {
- if ( tabIdToTimer[tabId] ) {
+ return function (tabId) {
+ if (tabIdToTimer[tabId]) {
return;
}
- if ( vAPI.isBehindTheSceneTabId(tabId) ) {
+
+ if (vAPI.isBehindTheSceneTabId(tabId)) {
return;
}
- tabIdToTimer[tabId] = vAPI.setTimeout(updateBadge.bind(this, tabId), 750);
+
+ tabIdToTimer[tabId] =
+ vAPI.setTimeout(updateBadge.bind(this, tabId), 750);
};
})();
- /******************************************************************************/
+ ηm.updateTitle = (function () {
+ let tabIdToTimer = Object.create(null);
+ let tabIdToTryCount = Object.create(null);
+ let delay = 499;
- ηm.updateTitle = (function() {
- var tabIdToTimer = Object.create(null);
- var tabIdToTryCount = Object.create(null);
- var delay = 499;
-
- var tryNoMore = function(tabId) {
+ let tryNoMore = function (tabId) {
delete tabIdToTryCount[tabId];
};
- var tryAgain = function(tabId) {
- var count = tabIdToTryCount[tabId];
- if ( count === undefined ) {
+ let tryAgain = function (tabId) {
+ let count = tabIdToTryCount[tabId];
+ if (count === undefined) {
return false;
}
- if ( count === 1 ) {
+
+ if (count === 1) {
delete tabIdToTryCount[tabId];
return false;
}
+
tabIdToTryCount[tabId] = count - 1;
- tabIdToTimer[tabId] = vAPI.setTimeout(updateTitle.bind(ηm, tabId), delay);
+ tabIdToTimer[tabId] =
+ vAPI.setTimeout(updateTitle.bind(ηm, tabId), delay);
return true;
};
- var onTabReady = function(tabId, tab) {
- if ( !tab ) {
+ let onTabReady = function (tabId, tab) {
+ if (!tab) {
return tryNoMore(tabId);
}
- var pageStore = this.pageStoreFromTabId(tabId);
- if ( pageStore === null ) {
+
+ let pageStore = this.pageStoreFromTabId(tabId);
+ if (pageStore === null) {
return tryNoMore(tabId);
}
- if ( !tab.title && tryAgain(tabId) ) {
+
+ if (!tab.title && tryAgain(tabId)) {
return;
}
+
// https://github.com/gorhill/uMatrix/issues/225
// Sometimes title changes while page is loading.
- var settled = tab.title && tab.title === pageStore.title;
+ let settled = tab.title && tab.title === pageStore.title;
pageStore.title = tab.title || tab.url || '';
this.pageStoresToken = Date.now();
- if ( settled || !tryAgain(tabId) ) {
+ if (settled || !tryAgain(tabId)) {
tryNoMore(tabId);
}
};
- var updateTitle = function(tabId) {
+ let updateTitle = function (tabId) {
delete tabIdToTimer[tabId];
vAPI.tabs.get(tabId, onTabReady.bind(this, tabId));
};
- return function(tabId) {
- if ( vAPI.isBehindTheSceneTabId(tabId) ) {
+ return function (tabId) {
+ if (vAPI.isBehindTheSceneTabId(tabId)) {
return;
}
- if ( tabIdToTimer[tabId] ) {
+
+ if (tabIdToTimer[tabId]) {
clearTimeout(tabIdToTimer[tabId]);
}
- tabIdToTimer[tabId] = vAPI.setTimeout(updateTitle.bind(this, tabId), delay);
+
+ tabIdToTimer[tabId] =
+ vAPI.setTimeout(updateTitle.bind(this, tabId), delay);
tabIdToTryCount[tabId] = 5;
};
})();
- /******************************************************************************/
-
// Stale page store entries janitor
// https://github.com/chrisaljoudi/uBlock/issues/455
- (function() {
- var cleanupPeriod = 7 * 60 * 1000;
- var cleanupSampleAt = 0;
- var cleanupSampleSize = 11;
-
- var cleanup = function() {
- var vapiTabs = vAPI.tabs;
- var tabIds = Object.keys(ηm.pageStores).sort();
- var checkTab = function(tabId) {
- vapiTabs.get(tabId, function(tab) {
- if ( !tab ) {
+ (function () {
+ let cleanupPeriod = 7 * 60 * 1000;
+ let cleanupSampleAt = 0;
+ let cleanupSampleSize = 11;
+
+ let cleanup = function () {
+ let tabIds = Object.keys(ηm.pageStores).sort();
+ let checkTab = function(tabId) {
+ vAPI.tabs.get(tabId, function (tab) {
+ if (!tab) {
ηm.unbindTabFromPageStats(tabId);
}
});
};
- if ( cleanupSampleAt >= tabIds.length ) {
+ if (cleanupSampleAt >= tabIds.length) {
cleanupSampleAt = 0;
}
- var tabId;
- var n = Math.min(cleanupSampleAt + cleanupSampleSize, tabIds.length);
- for ( var i = cleanupSampleAt; i < n; i++ ) {
+
+ let tabId;
+ let n =
+ Math.min(cleanupSampleAt + cleanupSampleSize, tabIds.length);
+
+ for (let i=cleanupSampleAt; i<n; i++) {
tabId = tabIds[i];
- if ( vAPI.isBehindTheSceneTabId(tabId) ) {
+ if (vAPI.isBehindTheSceneTabId(tabId)) {
continue;
}
checkTab(tabId);
@@ -714,7 +751,4 @@ housekeep itself.
vAPI.setTimeout(cleanup, cleanupPeriod);
})();
-
- /******************************************************************************/
-
})();
diff --git a/js/traffic.js b/js/traffic.js
index 6a6f700..8e408cf 100644
--- a/js/traffic.js
+++ b/js/traffic.js
@@ -29,6 +29,8 @@
ηMatrix.webRequest = (function() {
+ Cu.import('chrome://ematrix/content/lib/UriTools.jsm');
+
/******************************************************************************/
// Intercept and filter web requests according to white and black lists.
@@ -36,7 +38,7 @@
var onBeforeRootFrameRequestHandler = function(details) {
var ηm = ηMatrix;
var requestURL = details.url;
- var requestHostname = ηm.URI.hostnameFromURI(requestURL);
+ var requestHostname = UriTools.hostnameFromURI(requestURL);
var tabId = details.tabId;
ηm.tabContextManager.push(tabId, requestURL);
@@ -76,7 +78,7 @@
var onBeforeRequestHandler = function(details) {
var ηm = ηMatrix,
- ηmuri = ηm.URI,
+ ηmuri = UriTools,
requestURL = details.url,
requestScheme = ηmuri.schemeFromURI(requestURL);
@@ -144,7 +146,7 @@
var onBeforeSendHeadersHandler = function(details) {
var ηm = ηMatrix,
- ηmuri = ηm.URI,
+ ηmuri = UriTools,
requestURL = details.url,
requestScheme = ηmuri.schemeFromURI(requestURL);
@@ -304,7 +306,7 @@
var csp = [],
cspReport = [],
rootHostname = tabContext.rootHostname,
- requestHostname = ηm.URI.hostnameFromURI(requestURL);
+ requestHostname = UriTools.hostnameFromURI(requestURL);
// Inline script tags.
if ( ηm.mustAllow(rootHostname, requestHostname, 'script' ) !== true ) {
diff --git a/js/user-rules.js b/js/user-rules.js
index 02ff787..4ab850b 100644
--- a/js/user-rules.js
+++ b/js/user-rules.js
@@ -21,79 +21,69 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global uDom */
-
'use strict';
-/******************************************************************************/
-
-(function() {
-
- /******************************************************************************/
-
+(function () {
// Switches before, rules after
- var directiveSort = function(a, b) {
- var aIsSwitch = a.indexOf(':') !== -1;
- var bIsSwitch = b.indexOf(':') !== -1;
- if ( aIsSwitch === bIsSwitch ) {
+ let directiveSort = function (a, b) {
+ let aIsSwitch = a.indexOf(':') !== -1;
+ let bIsSwitch = b.indexOf(':') !== -1;
+
+ if (aIsSwitch === bIsSwitch) {
return a.localeCompare(b);
}
+
return aIsSwitch ? -1 : 1;
};
- /******************************************************************************/
+ let processUserRules = function (response) {
+ let allRules = {};
+ let permanentRules = {};
+ let temporaryRules = {};
- var processUserRules = function(response) {
- var rules, rule, i;
- var allRules = {};
- var permanentRules = {};
- var temporaryRules = {};
- var onLeft, onRight;
-
- rules = response.permanentRules.split(/\n+/);
- i = rules.length;
- while ( i-- ) {
- rule = rules[i].trim();
- if ( rule.length !== 0 ) {
+ let rules = response.permanentRules.split(/\n+/);
+ for (let i=rules.length-1; i>=0; --i) {
+ let rule = rules[i].trim();
+ if (rule.length !== 0) {
permanentRules[rule] = allRules[rule] = true;
}
}
+
rules = response.temporaryRules.split(/\n+/);
- i = rules.length;
- while ( i-- ) {
- rule = rules[i].trim();
- if ( rule.length !== 0 ) {
+ for (let i=rules.length-1; i>=0; --i) {
+ let rule = rules[i].trim();
+ if (rule.length !== 0) {
temporaryRules[rule] = allRules[rule] = true;
}
}
- var permanentList = document.createDocumentFragment(),
- temporaryList = document.createDocumentFragment(),
- li;
+ let permanentList = document.createDocumentFragment();
+ let temporaryList = document.createDocumentFragment();
+ let li;
rules = Object.keys(allRules).sort(directiveSort);
- for ( i = 0; i < rules.length; i++ ) {
- rule = rules[i];
- onLeft = permanentRules.hasOwnProperty(rule);
- onRight = temporaryRules.hasOwnProperty(rule);
- if ( onLeft && onRight ) {
- li = document.createElement('li');
+ for (let i=0; i<rules.length; ++i) {
+ let rule = rules[i];
+ let onLeft = permanentRules.hasOwnProperty(rule);
+ let onRight = temporaryRules.hasOwnProperty(rule);
+
+ li = document.createElement('li');
+
+ if (onLeft && onRight) {
li.textContent = rule;
permanentList.appendChild(li);
li = document.createElement('li');
li.textContent = rule;
temporaryList.appendChild(li);
- } else if ( onLeft ) {
- li = document.createElement('li');
+ } else if (onLeft) {
li.textContent = rule;
permanentList.appendChild(li);
li = document.createElement('li');
li.textContent = rule;
li.className = 'notRight toRemove';
temporaryList.appendChild(li);
- } else if ( onRight ) {
- li = document.createElement('li');
+ } else if (onRight) {
li.textContent = '\xA0';
permanentList.appendChild(li);
li = document.createElement('li');
@@ -109,17 +99,16 @@
document.querySelector('#diff > .left > ul').appendChild(permanentList);
uDom('#diff > .right > ul > li').remove();
document.querySelector('#diff > .right > ul').appendChild(temporaryList);
- uDom('#diff').toggleClass('dirty', response.temporaryRules !== response.permanentRules);
+ uDom('#diff')
+ .toggleClass('dirty',
+ response.temporaryRules !== response.permanentRules);
};
- /******************************************************************************/
-
// https://github.com/chrisaljoudi/uBlock/issues/757
// Support RequestPolicy rule syntax
-
- var fromRequestPolicy = function(content) {
- var matches = /\[origins-to-destinations\]([^\[]+)/.exec(content);
- if ( matches === null || matches.length !== 2 ) {
+ let fromRequestPolicy = function (content) {
+ let matches = /\[origins-to-destinations\]([^\[]+)/.exec(content);
+ if (matches === null || matches.length !== 2) {
return;
}
return matches[1].trim()
@@ -127,88 +116,95 @@
.replace(/\n/g, ' * allow\n');
};
- /******************************************************************************/
-
// https://github.com/gorhill/uMatrix/issues/270
+ let fromNoScript = function (content) {
+ let noscript = null;
- var fromNoScript = function(content) {
- var noscript = null;
try {
noscript = JSON.parse(content);
} catch (e) {
}
- if (
- noscript === null ||
- typeof noscript !== 'object' ||
- typeof noscript.prefs !== 'object' ||
- typeof noscript.prefs.clearClick === 'undefined' ||
- typeof noscript.whitelist !== 'string' ||
- typeof noscript.V !== 'string'
- ) {
+
+ if (noscript === null
+ || typeof noscript !== 'object'
+ || typeof noscript.prefs !== 'object'
+ || typeof noscript.prefs.clearClick === 'undefined'
+ || typeof noscript.whitelist !== 'string'
+ || typeof noscript.V !== 'string') {
return;
}
- var out = new Set();
- var reBad = /[a-z]+:\w*$/;
- var reURL = /[a-z]+:\/\/([0-9a-z.-]+)/;
- var directives = noscript.whitelist.split(/\s+/);
- var i = directives.length;
- var directive, matches;
- while ( i-- ) {
- directive = directives[i].trim();
- if ( directive === '' ) {
+
+ let out = new Set();
+ let reBad = /[a-z]+:\w*$/;
+ let reURL = /[a-z]+:\/\/([0-9a-z.-]+)/;
+ let directives = noscript.whitelist.split(/\s+/);
+
+ for (let i=directives.length-1; i>=0; --i) {
+ let directive = directives[i].trim();
+ if (directive === '') {
continue;
}
- if ( reBad.test(directive) ) {
+ if (reBad.test(directive)) {
continue;
}
- matches = reURL.exec(directive);
- if ( matches !== null ) {
+
+ let matches = reURL.exec(directive);
+ if (matches !== null) {
directive = matches[1];
}
+
out.add('* ' + directive + ' * allow');
out.add('* ' + directive + ' script allow');
out.add('* ' + directive + ' frame allow');
}
+
return Array.from(out).join('\n');
};
- /******************************************************************************/
-
- var handleImportFilePicker = function() {
- var fileReaderOnLoadHandler = function() {
- if ( typeof this.result !== 'string' || this.result === '' ) {
+ let handleImportFilePicker = function () {
+ let fileReaderOnLoadHandler = function () {
+ if (typeof this.result !== 'string' || this.result === '') {
return;
}
- var result = fromRequestPolicy(this.result);
- if ( result === undefined ) {
+
+ let result = fromRequestPolicy(this.result);
+ if (result === undefined) {
result = fromNoScript(this.result);
- if ( result === undefined ) {
+ if (result === undefined) {
result = this.result;
}
}
- if ( this.result === '' ) { return; }
- var request = {
+
+ if (this.result === '') {
+ return;
+ }
+
+ let request = {
'what': 'setUserRules',
- 'temporaryRules': rulesFromHTML('#diff .right li') + '\n' + result
+ 'temporaryRules': rulesFromHTML('#diff .right li')
+ + '\n' + result,
};
+
vAPI.messaging.send('user-rules.js', request, processUserRules);
};
+
var file = this.files[0];
- if ( file === undefined || file.name === '' ) {
+ if (file === undefined || file.name === '') {
return;
}
- if ( file.type.indexOf('text') !== 0 && file.type !== 'application/json') {
+
+ if (file.type.indexOf('text') !== 0
+ && file.type !== 'application/json') {
return;
}
- var fr = new FileReader();
+
+ let fr = new FileReader();
fr.onload = fileReaderOnLoadHandler;
fr.readAsText(file);
};
- /******************************************************************************/
-
- var startImportFilePicker = function() {
- var input = document.getElementById('importFilePicker');
+ let startImportFilePicker = function () {
+ let input = document.getElementById('importFilePicker');
// Reset to empty string, this will ensure an change event is properly
// triggered if the user pick a file, even if it is the same as the last
// one picked.
@@ -216,112 +212,105 @@
input.click();
};
- /******************************************************************************/
-
function exportUserRulesToFile() {
vAPI.download({
- 'url': 'data:text/plain,' + encodeURIComponent(rulesFromHTML('#diff .left li') + '\n'),
- 'filename': uDom('[data-i18n="userRulesDefaultFileName"]').text()
+ 'url': 'data:text/plain,'
+ + encodeURIComponent(rulesFromHTML('#diff .left li') + '\n'),
+ 'filename': uDom('[data-i18n="userRulesDefaultFileName"]').text(),
});
}
- /******************************************************************************/
-
var rulesFromHTML = function(selector) {
- var rules = [];
- var lis = uDom(selector);
- var li;
- for ( var i = 0; i < lis.length; i++ ) {
- li = lis.at(i);
- if ( li.hasClassName('toRemove') ) {
+ let rules = [];
+ let lis = uDom(selector);
+
+ for (let i=0; i<lis.length; ++i) {
+ let li = lis.at(i);
+ if (li.hasClassName('toRemove')) {
rules.push('');
} else {
rules.push(li.text());
}
}
+
return rules.join('\n');
};
- /******************************************************************************/
-
- var revertHandler = function() {
- var request = {
+ let revertHandler = function () {
+ let request = {
'what': 'setUserRules',
- 'temporaryRules': rulesFromHTML('#diff .left li')
+ 'temporaryRules': rulesFromHTML('#diff .left li'),
};
+
vAPI.messaging.send('user-rules.js', request, processUserRules);
};
- /******************************************************************************/
-
- var commitHandler = function() {
+ let commitHandler = function () {
var request = {
'what': 'setUserRules',
- 'permanentRules': rulesFromHTML('#diff .right li')
+ 'permanentRules': rulesFromHTML('#diff .right li'),
};
+
vAPI.messaging.send('user-rules.js', request, processUserRules);
};
- /******************************************************************************/
-
- var editStartHandler = function() {
+ let editStartHandler = function () {
uDom('#diff .right textarea').val(rulesFromHTML('#diff .right li'));
- var parent = uDom(this).ancestors('#diff');
+ let parent = uDom(this).ancestors('#diff');
parent.toggleClass('edit', true);
};
- /******************************************************************************/
-
- var editStopHandler = function() {
- var parent = uDom(this).ancestors('#diff');
+ let editStopHandler = function () {
+ let parent = uDom(this).ancestors('#diff');
parent.toggleClass('edit', false);
- var request = {
+
+ let request = {
'what': 'setUserRules',
- 'temporaryRules': uDom('#diff .right textarea').val()
+ 'temporaryRules': uDom('#diff .right textarea').val(),
};
+
vAPI.messaging.send('user-rules.js', request, processUserRules);
};
- /******************************************************************************/
-
- var editCancelHandler = function() {
- var parent = uDom(this).ancestors('#diff');
+ let editCancelHandler = function () {
+ let parent = uDom(this).ancestors('#diff');
parent.toggleClass('edit', false);
};
- /******************************************************************************/
-
- var temporaryRulesToggler = function() {
+ let temporaryRulesToggler = function() {
var li = uDom(this);
li.toggleClass('toRemove');
- var request = {
+
+ let request = {
'what': 'setUserRules',
- 'temporaryRules': rulesFromHTML('#diff .right li')
+ 'temporaryRules': rulesFromHTML('#diff .right li'),
};
+
vAPI.messaging.send('user-rules.js', request, processUserRules);
};
- /******************************************************************************/
-
- self.cloud.onPush = function() {
+ self.cloud.onPush = function () {
return rulesFromHTML('#diff .left li');
};
- self.cloud.onPull = function(data, append) {
- if ( typeof data !== 'string' ) { return; }
- if ( append ) {
+ self.cloud.onPull = function (data, append) {
+ if (typeof data !== 'string') {
+ return;
+ }
+
+ if (append) {
data = rulesFromHTML('#diff .right li') + '\n' + data;
}
- var request = {
+
+ let request = {
'what': 'setUserRules',
- 'temporaryRules': data
+ 'temporaryRules': data,
};
+
vAPI.messaging.send('user-rules.js', request, processUserRules);
};
- /******************************************************************************/
-
- uDom.onLoad(function() {
+ uDom.onLoad(function () {
// Handle user interaction
uDom('#importButton').on('click', startImportFilePicker);
uDom('#importFilePicker').on('change', handleImportFilePicker);
@@ -333,9 +322,8 @@
uDom('#editCancelButton').on('click', editCancelHandler);
uDom('#diff > .right > ul').on('click', 'li', temporaryRulesToggler);
- vAPI.messaging.send('user-rules.js', { what: 'getUserRules' }, processUserRules);
+ vAPI.messaging.send('user-rules.js', {
+ what: 'getUserRules',
+ }, processUserRules);
});
-
- /******************************************************************************/
-
})();
diff --git a/js/vapi-background.js b/js/vapi-background.js
index 7686bc9..e5e6998 100644
--- a/js/vapi-background.js
+++ b/js/vapi-background.js
@@ -22,7 +22,7 @@
*/
/* jshint bitwise: false, esnext: true */
-/* global self, Components, punycode */
+/* global self, Components */
// For background page
@@ -31,7 +31,9 @@
/******************************************************************************/
(function () {
- Cu.import('chrome://ematrix/content/HttpRequestHeaders.jsm');
+ Cu.import('chrome://ematrix/content/lib/HttpRequestHeaders.jsm');
+ Cu.import('chrome://ematrix/content/lib/PendingRequests.jsm');
+ Cu.import('chrome://ematrix/content/lib/Punycode.jsm');
// Icon-related stuff
vAPI.setIcon = function (tabId, iconId, badge) {
@@ -134,8 +136,6 @@
return this.QueryInterface(iid);
},
register: function () {
- this.pendingRingBufferInit();
-
Services.obs.addObserver(this, 'http-on-modify-request', true);
Services.obs.addObserver(this, 'http-on-examine-response', true);
Services.obs.addObserver(this, 'http-on-examine-cached-response', true);
@@ -174,82 +174,6 @@
this.contractID,
false);
},
- PendingRequest: function () {
- this.rawType = 0;
- this.tabId = 0;
- this._key = ''; // key is url, from URI.spec
- },
- // If all work fine, this map should not grow indefinitely. It
- // can have stale items in it, but these will be taken care of
- // when entries in the ring buffer are overwritten.
- pendingURLToIndex: new Map(),
- pendingWritePointer: 0,
- pendingRingBuffer: new Array(256),
- pendingRingBufferInit: function () {
- // Use and reuse pre-allocated PendingRequest objects =
- // less memory churning.
- for (let i=this.pendingRingBuffer.length-1; i>=0; --i) {
- this.pendingRingBuffer[i] = new this.PendingRequest();
- }
- },
- createPendingRequest: function (url) {
- // Pending request ring buffer:
- // +-------+-------+-------+-------+-------+-------+-------
- // |0 |1 |2 |3 |4 |5 |...
- // +-------+-------+-------+-------+-------+-------+-------
- //
- // URL to ring buffer index map:
- // { k = URL, s = ring buffer indices }
- //
- // s is a string which character codes map to ring buffer
- // indices -- for when the same URL is received multiple times
- // by shouldLoadListener() before the existing one is serviced
- // by the network request observer. I believe the use of a
- // string in lieu of an array reduces memory churning.
- let bucket;
- let i = this.pendingWritePointer;
- this.pendingWritePointer = i + 1 & 255;
-
- let preq = this.pendingRingBuffer[i];
- let si = String.fromCharCode(i);
-
- // Cleanup unserviced pending request
- if (preq._key !== '') {
- bucket = this.pendingURLToIndex.get(preq._key);
- if (bucket.length === 1) {
- this.pendingURLToIndex.delete(preq._key);
- } else {
- let pos = bucket.indexOf(si);
- this.pendingURLToIndex.set(preq._key,
- bucket.slice(0, pos)
- + bucket.slice(pos + 1));
- }
- }
-
- bucket = this.pendingURLToIndex.get(url);
- this.pendingURLToIndex.set(url, bucket === undefined
- ? si
- : bucket + si);
- preq._key = url;
- return preq;
- },
- lookupPendingRequest: function (url) {
- let bucket = this.pendingURLToIndex.get(url);
- if (bucket === undefined) {
- return null;
- }
-
- let i = bucket.charCodeAt(0);
- if (bucket.length === 1) {
- this.pendingURLToIndex.delete(url);
- } else {
- this.pendingURLToIndex.set(url, bucket.slice(1));
- }
-
- let preq = this.pendingRingBuffer[i];
- preq._key = ''; // mark as "serviced"
- return preq;
- },
handleRequest: function (channel, URI, tabId, rawType) {
let type = this.typeMap[rawType] || 'other';
@@ -460,7 +384,8 @@
// The channel was never serviced.
let tabId;
- let pendingRequest = this.lookupPendingRequest(URI.asciiSpec);
+ let pendingRequest =
+ PendingRequestBuffer.lookupRequest(URI.asciiSpec);
let rawType = 1;
let loadInfo = channel.loadInfo;
@@ -540,12 +465,7 @@
codePath: ''
};
- // Non-Fennec: common code paths.
(function () {
- if (vAPI.fennec) {
- return;
- }
-
let tbb = vAPI.toolbarButton;
let popupCommittedWidth = 0;
let popupCommittedHeight = 0;
@@ -571,8 +491,16 @@
button.setAttribute('badge', icon && icon.badge || '');
button.classList.toggle('off', !icon || !icon.img);
- let iconId = icon && icon.img ? icon.img : 'off';
- icon = 'url(' + vAPI.getURL('img/browsericons/icon19-' + iconId + '.png') + ')';
+ let iconId = (ηMatrix.userSettings.disableUpdateIcon) ?
+ icon && icon.img ? '19' : 'off' :
+ icon && icon.img ? icon.img : 'off';
+
+ icon = 'url('
+ + vAPI.getURL('img/browsericons/icon19-'
+ + iconId
+ + '.png')
+ + ')';
+
button.style.listStyleImage = icon;
};
@@ -814,12 +742,12 @@
// Found our button on this toolbar - but where on it?
let before = null;
- for (let i = index+1; i<currentset.length; ++i) {
+ for (let i=index+1; i<currentset.length; ++i) {
// The [id=...] notation doesn't work on
// space elements as they get a random ID each session
// (or something like that)
- // https://libregit.org/heckyel/ematrix/issues/5
- // https://libregit.org/heckyel/ematrix/issues/6
+ // https://gitlab.com/vannilla/ematrix/issues/5
+ // https://gitlab.com/vannilla/ematrix/issues/6
// Based on JustOff's snippet from the Pale Moon
// forum. It was reorganized because I find it
@@ -1246,7 +1174,7 @@
// Likelihood is that we do not have to punycode: given punycode overhead,
// it's faster to check and skip than do it unconditionally all the time.
- var punycodeHostname = punycode.toASCII;
+ var punycodeHostname = Punycode.toASCII;
var isNotASCII = /[^\x21-\x7F]/;
vAPI.punycodeHostname = function (hostname) {
diff --git a/js/vapi-core.js b/js/vapi-core.js
index 94ae599..fe80d7c 100644
--- a/js/vapi-core.js
+++ b/js/vapi-core.js
@@ -111,12 +111,9 @@
// }
// frameModule needs to be cleared too
- let frameModuleURL = vAPI.getURL('frameModule.js');
- let frameModule = {};
-
- Cu.import(frameModuleURL, frameModule);
- frameModule.contentObserver.unregister();
- Cu.unload(frameModuleURL);
+ Cu.import('chrome://ematrix/content/lib/FrameModule.jsm');
+ contentObserver.unregister();
+ Cu.unload('chrome://ematrix/content/lib/FrameModule.jsm');
});
vAPI.noTabId = '-1';
diff --git a/js/vapi-messaging.js b/js/vapi-messaging.js
index b4f468f..3c8ab02 100644
--- a/js/vapi-messaging.js
+++ b/js/vapi-messaging.js
@@ -26,7 +26,7 @@
/******************************************************************************/
(function () {
- Cu.import('chrome://ematrix/content/CallbackWrapper.jsm');
+ Cu.import('chrome://ematrix/content/lib/CallbackWrapper.jsm');
vAPI.messaging = {
get globalMessageManager() {
diff --git a/js/vapi-net.js b/js/vapi-net.js
index f8d1052..086e596 100644
--- a/js/vapi-net.js
+++ b/js/vapi-net.js
@@ -26,6 +26,8 @@
/******************************************************************************/
(function () {
+ Cu.import('chrome://ematrix/content/lib/PendingRequests.jsm');
+
vAPI.net = {};
vAPI.net.registerListeners = function () {
@@ -40,7 +42,8 @@
let shouldLoadListenerMessageName = location.host + ':shouldLoad';
let shouldLoadListener = function (e) {
let details = e.data;
- let pendingReq = vAPI.httpObserver.createPendingRequest(details.url);
+ let pendingReq =
+ PendingRequestBuffer.createRequest(details.url);
pendingReq.rawType = details.rawType;
pendingReq.tabId = vAPI.tabs.manager.tabIdFromTarget(e.target);
};