aboutsummaryrefslogtreecommitdiffstats
path: root/js/hosts-files.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/hosts-files.js')
-rw-r--r--js/hosts-files.js407
1 files changed, 209 insertions, 198 deletions
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();
-
- /******************************************************************************/
-
})();