mirror of https://github.com/gorhill/uBlock.git
this fixes #6
This commit is contained in:
parent
a71b9b4712
commit
fe372e9a11
|
@ -12,16 +12,23 @@ div > p:first-child {
|
|||
div > p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
body > ul {
|
||||
margin: 0.5em 0 0 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
ul {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
ul > li {
|
||||
margin: 0.5em 0 3px 0;
|
||||
margin: 0.5em 0 0 0;
|
||||
padding: 0;
|
||||
font-size: 15px;
|
||||
list-style-type: none;
|
||||
}
|
||||
ul > li > ul {
|
||||
margin: 0.25em 0 0 0;
|
||||
}
|
||||
ul > li > ul > li {
|
||||
font-size: 14px;
|
||||
margin: 0 0 0 1em;
|
||||
|
@ -35,12 +42,18 @@ ul > li > ul > li {
|
|||
height: 16em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#externalLists {
|
||||
font-size: smaller;
|
||||
width: 48em;
|
||||
height: 8em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<ul id="options" style="margin:0.5em 0 0 0;padding-left:1em;list-style-type:none">
|
||||
<ul id="options">
|
||||
<li><button id="blacklistsApply" disabled="true" data-i18n="3pApplyChanges"></button>
|
||||
<li style="margin-top:0.75em"><input type="checkbox" id="parseAllABPHideFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1"></label>
|
||||
<span class="dim" id="3pParseAllABPHideFiltersPrompt2"></span>
|
||||
|
@ -48,9 +61,15 @@ ul > li > ul > li {
|
|||
<div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div>
|
||||
<li style="margin-top:0.75em"><p id="listsOfBlockedHostsPrompt"></p>
|
||||
</ul>
|
||||
<ul id="lists" style="margin:0.5em 0 0 0;padding-left:1em;list-style-type:none">
|
||||
<ul id="lists">
|
||||
</ul>
|
||||
|
||||
<div style="margin: 2em 0 0 2em">
|
||||
<p data-i18n="3pExternalListsHint" style="margin: 0 0 0.25em 0; font-size: 13px;"></p>
|
||||
<textarea id="externalLists"></textarea>
|
||||
<p style="margin: 0.25em 0 0 0"><button id="externalListsApply" disabled="true" data-i18n="3pExternalListsApply"></button></p>
|
||||
</div>
|
||||
|
||||
<script src="js/udom.js"></script>
|
||||
<script src="js/i18n.js"></script>
|
||||
<script src="js/dashboard-common.js"></script>
|
||||
|
|
|
@ -131,6 +131,18 @@
|
|||
"message":"Regions, languages",
|
||||
"description":"English: Regions, languages"
|
||||
},
|
||||
"3pGroupCustom":{
|
||||
"message":"Custom",
|
||||
"description":"English: Custom"
|
||||
},
|
||||
"3pExternalListsHint":{
|
||||
"message":"One URL per line. Lines prefixed with ‘!’ will be ignored. Invalid URLs will be silently ignored.",
|
||||
"description":"English: One URL per line. Lines prefixed with ‘!’ will be ignored. Invalid URLs will be silently ignored."
|
||||
},
|
||||
"3pExternalListsApply":{
|
||||
"message":"Apply",
|
||||
"description":"English: Apply"
|
||||
},
|
||||
"1pFormatHint":{
|
||||
"message":"One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with ‘!’ will be ignored.",
|
||||
"description":"English: One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with ‘!’ will be ignored."
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
www.zerohedge.com##.similar-box
|
||||
|
||||
# https://github.com/gorhill/uBlock/issues/57
|
||||
# https://github.com/gorhill/uBlock/issues/98
|
||||
# New filter class: entity filters, where
|
||||
# entity = domain minus public suffix
|
||||
# The following filters were taken out of EasyList and given an entity name,
|
||||
|
|
|
@ -48,7 +48,7 @@ a {
|
|||
display: none;
|
||||
border: 1px dotted black;
|
||||
background-color: #F8F8F8;
|
||||
font-size: 90%;
|
||||
font-size: 13px;
|
||||
}
|
||||
.whatisthis-expandable > p {
|
||||
margin-top: 1em;
|
||||
|
|
212
js/3p-filters.js
212
js/3p-filters.js
|
@ -28,12 +28,13 @@
|
|||
/******************************************************************************/
|
||||
|
||||
var userListName = chrome.i18n.getMessage('1pPageName');
|
||||
var selectedBlacklistsHash = '';
|
||||
var listURLPrefix = 'asset-viewer.html?url=';
|
||||
var listDetails = {};
|
||||
var parseCosmeticFilters = true;
|
||||
var externalLists = '';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
messaging.start('lists.js');
|
||||
messaging.start('3p-filters.js');
|
||||
|
||||
var onMessage = function(msg) {
|
||||
switch ( msg.what ) {
|
||||
|
@ -67,8 +68,6 @@ var renderNumber = function(value) {
|
|||
|
||||
var renderBlacklists = function() {
|
||||
// empty list first
|
||||
uDom('#lists .listDetails').remove();
|
||||
|
||||
var µb = getµb();
|
||||
|
||||
uDom('#listsOfBlockedHostsPrompt').text(
|
||||
|
@ -111,19 +110,22 @@ var renderBlacklists = function() {
|
|||
var listStatsTemplate = chrome.i18n.getMessage('3pListsOfBlockedHostsPerListStats');
|
||||
|
||||
var htmlFromBranch = function(groupKey, listKeys, lists) {
|
||||
listKeys.sort(function(a, b) {
|
||||
return lists[a].title.localeCompare(lists[b].title);
|
||||
});
|
||||
var html = [
|
||||
'<li>',
|
||||
chrome.i18n.getMessage('3pGroup' + groupKey.charAt(0).toUpperCase() + groupKey.slice(1)),
|
||||
'<ul>'
|
||||
];
|
||||
if ( !listKeys ) {
|
||||
return html.join('');
|
||||
}
|
||||
listKeys.sort(function(a, b) {
|
||||
return lists[a].title.localeCompare(lists[b].title);
|
||||
});
|
||||
var listEntryTemplate = [
|
||||
'<li class="listDetails">',
|
||||
'<input type="checkbox" {{checked}}>',
|
||||
' ',
|
||||
'<a href="', listURLPrefix, '{{URL}}" type="text/plain">',
|
||||
'<a href="{{URL}}" type="text/plain">',
|
||||
'{{name}}',
|
||||
'</a>',
|
||||
': ',
|
||||
|
@ -140,7 +142,7 @@ var renderBlacklists = function() {
|
|||
.replace('{{URL}}', encodeURI(listKey))
|
||||
.replace('{{name}}', htmlFromListName(list.title, listKey))
|
||||
.replace('{{used}}', !list.off && !isNaN(+list.entryUsedCount) ? renderNumber(list.entryUsedCount) : '0')
|
||||
.replace('{{total}}', !isNaN(+list.entryCount) ? renderNumber(list.entryCount) : '?')
|
||||
.replace('{{total}}', !isNaN(+list.entryCount) ? renderNumber(list.entryCount) : '?');
|
||||
html.push(listEntry);
|
||||
}
|
||||
html.push('</ul>');
|
||||
|
@ -164,58 +166,84 @@ var renderBlacklists = function() {
|
|||
return groups;
|
||||
};
|
||||
|
||||
var html = [];
|
||||
var groups = groupsFromLists(µb.remoteBlacklists);
|
||||
var groupKey;
|
||||
var groupKeys = [
|
||||
'default',
|
||||
'ads',
|
||||
'privacy',
|
||||
'malware',
|
||||
'social',
|
||||
'multipurpose',
|
||||
'regions'
|
||||
];
|
||||
for ( var i = 0; i < groupKeys.length; i++ ) {
|
||||
groupKey = groupKeys[i];
|
||||
html.push(htmlFromBranch(groupKey, groups[groupKey], µb.remoteBlacklists));
|
||||
delete groups[groupKey];
|
||||
}
|
||||
// For all groups not covered above (if any left)
|
||||
groupKeys = Object.keys(groups);
|
||||
for ( var i = 0; i < groupKeys.length; i++ ) {
|
||||
groupKey = groupKeys[i];
|
||||
html.push(htmlFromBranch(groupKey, groups[groupKey], µb.remoteBlacklists));
|
||||
delete groups[groupKey];
|
||||
}
|
||||
var onListsReceived = function(details) {
|
||||
listDetails = details;
|
||||
|
||||
uDom('#lists').html(html.join(''));
|
||||
uDom('#parseAllABPHideFilters').prop('checked', µb.userSettings.parseAllABPHideFilters === true);
|
||||
uDom('#ubiquitousParseAllABPHideFiltersPrompt2').text(
|
||||
chrome.i18n.getMessage("listsParseAllABPHideFiltersPrompt2")
|
||||
.replace('{{abpHideFilterCount}}', renderNumber(µb.abpHideFilters.getFilterCount()))
|
||||
);
|
||||
var lists = details.available;
|
||||
var html = [];
|
||||
var groups = groupsFromLists(lists);
|
||||
var groupKey, i;
|
||||
var groupKeys = [
|
||||
'default',
|
||||
'ads',
|
||||
'privacy',
|
||||
'malware',
|
||||
'social',
|
||||
'multipurpose',
|
||||
'regions',
|
||||
'custom'
|
||||
];
|
||||
for ( i = 0; i < groupKeys.length; i++ ) {
|
||||
groupKey = groupKeys[i];
|
||||
html.push(htmlFromBranch(groupKey, groups[groupKey], lists));
|
||||
delete groups[groupKey];
|
||||
}
|
||||
// For all groups not covered above (if any left)
|
||||
groupKeys = Object.keys(groups);
|
||||
for ( i = 0; i < groupKeys.length; i++ ) {
|
||||
groupKey = groupKeys[i];
|
||||
html.push(htmlFromBranch(groupKey, groups[groupKey], lists));
|
||||
delete groups[groupKey];
|
||||
}
|
||||
|
||||
uDom('a').attr('target', '_blank');
|
||||
selectedBlacklistsHash = getSelectedBlacklistsHash();
|
||||
uDom('#lists .listDetails').remove();
|
||||
uDom('#lists').html(html.join(''));
|
||||
uDom('#parseAllABPHideFilters').prop('checked', listDetails.cosmetic === true);
|
||||
uDom('#ubiquitousParseAllABPHideFiltersPrompt2').text(
|
||||
chrome.i18n.getMessage("listsParseAllABPHideFiltersPrompt2")
|
||||
.replace('{{abpHideFilterCount}}', renderNumber(µb.abpHideFilters.getFilterCount()))
|
||||
);
|
||||
uDom('a').attr('target', '_blank');
|
||||
selectedBlacklistsChanged();
|
||||
};
|
||||
|
||||
messaging.ask({ what: 'getLists' }, onListsReceived);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Create a hash so that we know whether the selection of preset blacklists
|
||||
// has changed.
|
||||
// Check whether lists need reloading.
|
||||
|
||||
var getSelectedBlacklistsHash = function() {
|
||||
var hash = '';
|
||||
var inputs = uDom('#lists .listDetails > input');
|
||||
var i = inputs.length();
|
||||
while ( i-- ) {
|
||||
hash += inputs.subset(i).prop('checked').toString();
|
||||
var needToReload = function() {
|
||||
if ( listDetails.cosmetic !== getµb().userSettings.parseAllABPHideFilters ) {
|
||||
return true;
|
||||
}
|
||||
// Factor in whether cosmetic filters are to be processed
|
||||
hash += uDom('#parseAllABPHideFilters').prop('checked').toString();
|
||||
|
||||
return hash;
|
||||
var availableLists = listDetails.available;
|
||||
var currentLists = listDetails.current;
|
||||
var location, availableOff, currentOff;
|
||||
// This check existing entries
|
||||
for ( location in availableLists ) {
|
||||
if ( availableLists.hasOwnProperty(location) === false ) {
|
||||
continue;
|
||||
}
|
||||
availableOff = availableLists[location].off === true;
|
||||
currentOff = currentLists[location] === undefined || currentLists[location].off === true;
|
||||
if ( availableOff !== currentOff ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// This check removed entries
|
||||
for ( location in currentLists ) {
|
||||
if ( currentLists.hasOwnProperty(location) === false ) {
|
||||
continue;
|
||||
}
|
||||
currentOff = currentLists[location].off === true;
|
||||
availableOff = availableLists[location] === undefined || availableLists[location].off === true;
|
||||
if ( availableOff !== currentOff ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -223,10 +251,21 @@ var getSelectedBlacklistsHash = function() {
|
|||
// This is to give a visual hint that the selection of blacklists has changed.
|
||||
|
||||
var selectedBlacklistsChanged = function() {
|
||||
uDom('#blacklistsApply').prop(
|
||||
'disabled',
|
||||
getSelectedBlacklistsHash() === selectedBlacklistsHash
|
||||
);
|
||||
uDom('#blacklistsApply').prop('disabled', !needToReload());
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onListCheckboxChanged = function() {
|
||||
var href = uDom(this).parent().find('a').first().attr('href');
|
||||
if ( typeof href !== 'string' ) {
|
||||
return;
|
||||
}
|
||||
if ( listDetails.available[href] === undefined ) {
|
||||
return;
|
||||
}
|
||||
listDetails.available[href].off = !this.checked;
|
||||
selectedBlacklistsChanged();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -242,11 +281,16 @@ var onListLinkClicked = function(ev) {
|
|||
/******************************************************************************/
|
||||
|
||||
var blacklistsApplyHandler = function() {
|
||||
var newHash = getSelectedBlacklistsHash();
|
||||
if ( newHash === selectedBlacklistsHash ) {
|
||||
if ( !needToReload() ) {
|
||||
return;
|
||||
}
|
||||
// Reload blacklists
|
||||
messaging.tell({
|
||||
what: 'userSettings',
|
||||
name: 'parseAllABPHideFilters',
|
||||
value: parseCosmeticFilters
|
||||
});
|
||||
// Reload blacklists
|
||||
var switches = [];
|
||||
var lis = uDom('#lists .listDetails');
|
||||
var i = lis.length();
|
||||
|
@ -255,8 +299,7 @@ var blacklistsApplyHandler = function() {
|
|||
path = lis
|
||||
.subset(i)
|
||||
.find('a')
|
||||
.attr('href')
|
||||
.replace(listURLPrefix, '');
|
||||
.attr('href');
|
||||
switches.push({
|
||||
location: path,
|
||||
off: lis.subset(i).find('input').prop('checked') === false
|
||||
|
@ -266,30 +309,61 @@ var blacklistsApplyHandler = function() {
|
|||
what: 'reloadAllFilters',
|
||||
switches: switches
|
||||
});
|
||||
uDom('#blacklistsApply').prop('disabled', true );
|
||||
uDom('#blacklistsApply').prop('disabled', true);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var abpHideFiltersCheckboxChanged = function() {
|
||||
listDetails.cosmetic = this.checked;
|
||||
selectedBlacklistsChanged();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var renderExternalLists = function() {
|
||||
var onReceived = function(details) {
|
||||
uDom('#externalLists').val(details);
|
||||
externalLists = details;
|
||||
};
|
||||
messaging.ask({ what: 'userSettings', name: 'externalLists' }, onReceived);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var externalListsChangeHandler = function() {
|
||||
uDom('#externalListsApply').prop(
|
||||
'disabled',
|
||||
this.value.trim() === externalLists
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var externalListsApplyHandler = function() {
|
||||
externalLists = uDom('#externalLists').val();
|
||||
messaging.tell({
|
||||
what: 'userSettings',
|
||||
name: 'parseAllABPHideFilters',
|
||||
value: this.checked
|
||||
name: 'externalLists',
|
||||
value: externalLists
|
||||
});
|
||||
selectedBlacklistsChanged();
|
||||
renderBlacklists();
|
||||
uDom('#externalListsApply').prop('disabled', true);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uDom.onLoad(function() {
|
||||
// Handle user interaction
|
||||
uDom('#lists').on('change', '.listDetails', selectedBlacklistsChanged);
|
||||
uDom('#lists').on('click', '.listDetails > a:first-child', onListLinkClicked);
|
||||
uDom('#blacklistsApply').on('click', blacklistsApplyHandler);
|
||||
uDom('#parseAllABPHideFilters').on('change', abpHideFiltersCheckboxChanged);
|
||||
uDom('#blacklistsApply').on('click', blacklistsApplyHandler);
|
||||
uDom('#lists').on('change', '.listDetails > input', onListCheckboxChanged);
|
||||
uDom('#lists').on('click', '.listDetails > a:nth-of-type(1)', onListLinkClicked);
|
||||
uDom('#externalLists').on('input', externalListsChangeHandler);
|
||||
uDom('#externalListsApply').on('click', externalListsApplyHandler);
|
||||
|
||||
renderBlacklists();
|
||||
renderExternalLists();
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -122,7 +122,7 @@ var getUpdateList = function(callback) {
|
|||
}
|
||||
};
|
||||
|
||||
µBlock.assets.getRemote('assets/checksums.txt', onRemoteChecksumsLoaded);
|
||||
µBlock.assets.getRepo('assets/checksums.txt', onRemoteChecksumsLoaded);
|
||||
µBlock.assets.get('assets/checksums.txt', onLocalChecksumsLoaded);
|
||||
};
|
||||
|
||||
|
@ -200,6 +200,9 @@ var update = function(list, callback) {
|
|||
processList();
|
||||
};
|
||||
|
||||
// Purge obsolete external assets
|
||||
µBlock.assets.purge(/^https?:\/\/.+$/, Date.now() - µBlock.updateAssetsEvery);
|
||||
|
||||
if ( list ) {
|
||||
processList();
|
||||
} else {
|
||||
|
|
78
js/assets.js
78
js/assets.js
|
@ -146,7 +146,7 @@ var cachedAssetsManager = (function() {
|
|||
};
|
||||
var onEntries = function(entries) {
|
||||
if ( entries[path] === undefined ) {
|
||||
entries[path] = true;
|
||||
entries[path] = Date.now();
|
||||
bin.cached_asset_entries = entries;
|
||||
}
|
||||
chrome.storage.local.set(bin, onSaved);
|
||||
|
@ -154,7 +154,7 @@ var cachedAssetsManager = (function() {
|
|||
getEntries(onEntries);
|
||||
};
|
||||
|
||||
exports.remove = function(pattern) {
|
||||
exports.remove = function(pattern, before) {
|
||||
var onEntries = function(entries) {
|
||||
var keystoRemove = [];
|
||||
var paths = Object.keys(entries);
|
||||
|
@ -168,6 +168,9 @@ var cachedAssetsManager = (function() {
|
|||
if ( pattern instanceof RegExp && !pattern.test(path) ) {
|
||||
continue;
|
||||
}
|
||||
if ( typeof before === 'number' && entries[path] >= before ) {
|
||||
continue;
|
||||
}
|
||||
keystoRemove.push(cachedAssetPathPrefix + path);
|
||||
delete entries[path];
|
||||
}
|
||||
|
@ -406,7 +409,9 @@ var readLocalFile = function(path, callback) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var readRemoteFile = function(path, callback) {
|
||||
// Get the repository copy of a built-in asset.
|
||||
|
||||
var readRepoFile = function(path, callback) {
|
||||
var reportBack = function(content, err) {
|
||||
var details = {
|
||||
'path': path,
|
||||
|
@ -416,8 +421,8 @@ var readRemoteFile = function(path, callback) {
|
|||
callback(details);
|
||||
};
|
||||
|
||||
var onRemoteFileLoaded = function() {
|
||||
// console.log('µBlock> readRemoteFile() / onRemoteFileLoaded()');
|
||||
var onRepoFileLoaded = function() {
|
||||
// console.log('µBlock> readRepoFile() / onRepoFileLoaded()');
|
||||
// https://github.com/gorhill/httpswitchboard/issues/263
|
||||
if ( this.status === 200 ) {
|
||||
reportBack(this.responseText);
|
||||
|
@ -427,8 +432,8 @@ var readRemoteFile = function(path, callback) {
|
|||
this.onload = this.onerror = null;
|
||||
};
|
||||
|
||||
var onRemoteFileError = function(ev) {
|
||||
console.error('µBlock> readRemoteFile() / onRemoteFileError("%s")', path);
|
||||
var onRepoFileError = function(ev) {
|
||||
console.error('µBlock> readRepoFile() / onRepoFileError("%s")', path);
|
||||
reportBack('', 'Error');
|
||||
this.onload = this.onerror = null;
|
||||
};
|
||||
|
@ -436,13 +441,64 @@ var readRemoteFile = function(path, callback) {
|
|||
// 'ublock=...' is to skip browser cache
|
||||
getTextFileFromURL(
|
||||
repositoryRoot + path + '?ublock=' + Date.now(),
|
||||
onRemoteFileLoaded,
|
||||
onRemoteFileError
|
||||
onRepoFileLoaded,
|
||||
onRepoFileError
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var readExternalFile = function(path, callback) {
|
||||
var reportBack = function(content, err) {
|
||||
var details = {
|
||||
'path': path,
|
||||
'content': content
|
||||
};
|
||||
if ( err ) {
|
||||
details.error = err;
|
||||
}
|
||||
callback(details);
|
||||
};
|
||||
|
||||
var onExternalFileCached = function(details) {
|
||||
this.onload = this.onerror = null;
|
||||
// console.log('µBlock> onExternalFileCached()');
|
||||
reportBack(details.content);
|
||||
};
|
||||
|
||||
var onExternalFileLoaded = function() {
|
||||
this.onload = this.onerror = null;
|
||||
// console.log('µBlock> onExternalFileLoaded()');
|
||||
cachedAssetsManager.save(path, this.responseText, onExternalFileCached);
|
||||
};
|
||||
|
||||
var onExternalFileError = function(ev) {
|
||||
console.error('µBlock> onExternalFileError() / onLocalFileError("%s")', path);
|
||||
reportBack('', 'Error');
|
||||
this.onload = this.onerror = null;
|
||||
};
|
||||
|
||||
var onCachedContentLoaded = function(details) {
|
||||
// console.log('µBlock> readLocalFile() / onCacheFileLoaded()');
|
||||
reportBack(details.content);
|
||||
};
|
||||
|
||||
var onCachedContentError = function(details) {
|
||||
// console.error('µBlock> readLocalFile() / onCacheFileError("%s")', path);
|
||||
getTextFileFromURL(details.path, onExternalFileLoaded, onExternalFileError);
|
||||
};
|
||||
|
||||
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var purgeCache = function(pattern, before) {
|
||||
cachedAssetsManager.remove(pattern, before);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var writeLocalFile = function(path, content, callback) {
|
||||
cachedAssetsManager.save(path, content, callback);
|
||||
};
|
||||
|
@ -580,7 +636,9 @@ synchronizeCache();
|
|||
|
||||
return {
|
||||
'get': readLocalFile,
|
||||
'getRemote': readRemoteFile,
|
||||
'getExternal': readExternalFile,
|
||||
'getRepo': readRepoFile,
|
||||
'purge': purgeCache,
|
||||
'put': writeLocalFile,
|
||||
'update': updateFromRemote
|
||||
};
|
||||
|
|
|
@ -32,6 +32,7 @@ return {
|
|||
|
||||
userSettings: {
|
||||
collapseBlocked: true,
|
||||
externalLists: '',
|
||||
logBlockedRequests: false,
|
||||
logAllowedRequests: false,
|
||||
parseAllABPHideFilters: true,
|
||||
|
@ -47,13 +48,12 @@ return {
|
|||
projectServerRoot: 'https://raw.githubusercontent.com/gorhill/uBlock/master/',
|
||||
userFiltersPath: 'assets/user/filters.txt',
|
||||
|
||||
// list of remote blacklist locations
|
||||
remoteBlacklists: {
|
||||
// permanent lists
|
||||
permanentLists: {
|
||||
// User
|
||||
'assets/user/filters.txt': {
|
||||
group: 'default'
|
||||
},
|
||||
|
||||
// uBlock
|
||||
'assets/ublock/filters.txt': {
|
||||
title: 'µBlock filters',
|
||||
|
@ -64,7 +64,10 @@ return {
|
|||
title: 'µBlock filters - Privacy',
|
||||
group: 'default'
|
||||
}
|
||||
// 3rd-party lists fetched dynamically
|
||||
},
|
||||
|
||||
// current lists
|
||||
remoteBlacklists: {
|
||||
},
|
||||
|
||||
pageStores: {},
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
var InvalidCharacterError = function(message) {
|
||||
this.message = message;
|
||||
};
|
||||
InvalidCharacterError.prototype = new Error;
|
||||
InvalidCharacterError.prototype = new Error();
|
||||
InvalidCharacterError.prototype.name = 'InvalidCharacterError';
|
||||
|
||||
if (!CSS.escape) {
|
||||
|
|
|
@ -233,11 +233,28 @@ var onMessage = function(request, sender, callback) {
|
|||
|
||||
(function() {
|
||||
|
||||
var getLists = function(callback) {
|
||||
var µb = µBlock;
|
||||
var onReceived = function(lists) {
|
||||
callback({
|
||||
available: lists,
|
||||
current: µb.remoteBlacklists,
|
||||
cosmetic: µb.userSettings.parseAllABPHideFilters
|
||||
});
|
||||
};
|
||||
µb.getAvailableLists(onReceived);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onMessage = function(request, sender, callback) {
|
||||
var µb = µBlock;
|
||||
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
case 'getLists':
|
||||
return getLists(callback);
|
||||
|
||||
case 'readUserUbiquitousBlockRules':
|
||||
return µb.assets.get(µb.userFiltersPath, callback);
|
||||
|
||||
|
|
|
@ -138,6 +138,9 @@ function defaultHandler(request, sender, callback) {
|
|||
// Async
|
||||
switch ( request.what ) {
|
||||
case 'getAssetContent':
|
||||
if ( /^https?:\/\//.test(request.url) ) {
|
||||
return µBlock.assets.getExternal(request.url, callback);
|
||||
}
|
||||
return µBlock.assets.get(request.url, callback);
|
||||
|
||||
case 'loadUbiquitousAllowRules':
|
||||
|
|
|
@ -154,7 +154,7 @@ PageStore.prototype.updateBadge = function() {
|
|||
|
||||
var iconStr = '';
|
||||
if ( µb.userSettings.showIconBadge && netFilteringSwitch && this.perLoadBlockedRequestCount ) {
|
||||
iconStr = µb.formatCount(this.perLoadBlockedRequestCount);
|
||||
iconStr = this.perLoadBlockedRequestCount.toLocaleString();
|
||||
}
|
||||
chrome.browserAction.setBadgeText({
|
||||
tabId: this.tabId,
|
||||
|
|
180
js/storage.js
180
js/storage.js
|
@ -124,33 +124,100 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.loadUbiquitousBlacklists = function() {
|
||||
var blacklistLoadCount;
|
||||
var obsoleteBlacklists = [];
|
||||
µBlock.getAvailableLists = function(callback) {
|
||||
var availableLists = {};
|
||||
|
||||
var removeObsoleteBlacklistsHandler = function(store) {
|
||||
if ( !store.remoteBlacklists ) {
|
||||
return;
|
||||
}
|
||||
// selected lists
|
||||
var onSelectedListsLoaded = function(store) {
|
||||
var lists = store.remoteBlacklists;
|
||||
var locations = Object.keys(lists);
|
||||
var location;
|
||||
while ( location = obsoleteBlacklists.pop() ) {
|
||||
delete store.remoteBlacklists[location];
|
||||
|
||||
while ( location = locations.pop() ) {
|
||||
if ( !availableLists[location] ) {
|
||||
continue;
|
||||
}
|
||||
// https://github.com/gorhill/httpswitchboard/issues/218
|
||||
// Transfer potentially existing list title into restored list data.
|
||||
if ( lists[location].title !== availableLists[location].title ) {
|
||||
lists[location].title = availableLists[location].title;
|
||||
}
|
||||
availableLists[location] = lists[location];
|
||||
}
|
||||
chrome.storage.local.set(store);
|
||||
|
||||
callback(availableLists);
|
||||
};
|
||||
|
||||
var removeObsoleteBlacklists = function() {
|
||||
if ( obsoleteBlacklists.length === 0 ) {
|
||||
return;
|
||||
// built-in lists
|
||||
var onBuiltinListsLoaded = function(details) {
|
||||
var location, locations;
|
||||
try {
|
||||
locations = JSON.parse(details.content);
|
||||
} catch (e) {
|
||||
locations = {};
|
||||
}
|
||||
for ( location in locations ) {
|
||||
if ( locations.hasOwnProperty(location) === false ) {
|
||||
continue;
|
||||
}
|
||||
availableLists['assets/thirdparties/' + location] = locations[location];
|
||||
}
|
||||
|
||||
// Now get user's selection of lists
|
||||
chrome.storage.local.get(
|
||||
{ 'remoteBlacklists': µBlock.remoteBlacklists },
|
||||
removeObsoleteBlacklistsHandler
|
||||
{ 'remoteBlacklists': availableLists },
|
||||
onSelectedListsLoaded
|
||||
);
|
||||
};
|
||||
|
||||
// permanent lists
|
||||
var location;
|
||||
var lists = this.permanentLists;
|
||||
for ( location in lists ) {
|
||||
if ( lists.hasOwnProperty(location) === false ) {
|
||||
continue;
|
||||
}
|
||||
availableLists[location] = lists[location];
|
||||
}
|
||||
|
||||
// custom lists
|
||||
var c;
|
||||
var locations = this.userSettings.externalLists.split('\n');
|
||||
for ( var i = 0; i < locations.length; i++ ) {
|
||||
location = locations[i].trim();
|
||||
c = location.charAt(0);
|
||||
if ( location === '' || c === '!' || c === '#' ) {
|
||||
continue;
|
||||
}
|
||||
// Coarse validation
|
||||
if ( /[^0-9A-Za-z!*'();:@&=+$,\/?%#\[\]_.~-]/.test(location) ) {
|
||||
continue;
|
||||
}
|
||||
availableLists[location] = {
|
||||
title: '',
|
||||
group: 'custom',
|
||||
external: true
|
||||
};
|
||||
}
|
||||
|
||||
// get built-in block lists.
|
||||
this.assets.get('assets/ublock/filter-lists.json', onBuiltinListsLoaded);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.loadUbiquitousBlacklists = function() {
|
||||
var µb = this;
|
||||
var blacklistLoadCount;
|
||||
|
||||
var loadBlacklistsEnd = function() {
|
||||
µb.abpFilters.freeze();
|
||||
µb.abpHideFilters.freeze();
|
||||
µb.messaging.announce({ what: 'loadUbiquitousBlacklistCompleted' });
|
||||
chrome.storage.local.set({ 'remoteBlacklists': µb.remoteBlacklists });
|
||||
};
|
||||
|
||||
var mergeBlacklist = function(details) {
|
||||
var µb = µBlock;
|
||||
µb.mergeUbiquitousBlacklist(details);
|
||||
blacklistLoadCount -= 1;
|
||||
if ( blacklistLoadCount === 0 ) {
|
||||
|
@ -158,97 +225,38 @@
|
|||
}
|
||||
};
|
||||
|
||||
var loadBlacklistsEnd = function() {
|
||||
µBlock.abpFilters.freeze();
|
||||
µBlock.abpHideFilters.freeze();
|
||||
removeObsoleteBlacklists();
|
||||
µBlock.messaging.announce({ what: 'loadUbiquitousBlacklistCompleted' });
|
||||
};
|
||||
|
||||
var loadBlacklistsStart = function(store) {
|
||||
var µb = µBlock;
|
||||
var loadBlacklistsStart = function(lists) {
|
||||
µb.remoteBlacklists = lists;
|
||||
|
||||
// rhill 2013-12-10: set all existing entries to `false`.
|
||||
µb.abpFilters.reset();
|
||||
µb.abpHideFilters.reset();
|
||||
var storedLists = store.remoteBlacklists;
|
||||
var storedListLocations = Object.keys(storedLists);
|
||||
|
||||
blacklistLoadCount = storedListLocations.length;
|
||||
var locations = Object.keys(lists);
|
||||
blacklistLoadCount = locations.length;
|
||||
if ( blacklistLoadCount === 0 ) {
|
||||
loadBlacklistsEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
// Backward compatibility for when a list changes location
|
||||
var relocations = [
|
||||
{
|
||||
// https://github.com/gorhill/httpswitchboard/issues/361
|
||||
'bad': 'assets/thirdparties/adblock-czechoslovaklist.googlecode.com/svn/filters.txt',
|
||||
'good': 'assets/thirdparties/raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt'
|
||||
}
|
||||
];
|
||||
var relocation;
|
||||
while ( relocation = relocations.pop() ) {
|
||||
if ( µb.remoteBlacklists[relocation.good] && storedLists[relocation.bad] ) {
|
||||
storedLists[relocation.good].off = storedLists[relocation.bad].off;
|
||||
}
|
||||
}
|
||||
|
||||
// Load each preset blacklist which is not disabled.
|
||||
var location;
|
||||
while ( location = storedListLocations.pop() ) {
|
||||
// If loaded list location is not part of default list locations,
|
||||
// remove its entry from local storage.
|
||||
if ( !µb.remoteBlacklists[location] ) {
|
||||
obsoleteBlacklists.push(location);
|
||||
blacklistLoadCount -= 1;
|
||||
continue;
|
||||
}
|
||||
// https://github.com/gorhill/httpswitchboard/issues/218
|
||||
// Transfer potentially existing list title into restored list data.
|
||||
if ( storedLists[location].title !== µb.remoteBlacklists[location].title ) {
|
||||
storedLists[location].title = µb.remoteBlacklists[location].title;
|
||||
}
|
||||
// Store details of this preset blacklist
|
||||
µb.remoteBlacklists[location] = storedLists[location];
|
||||
while ( location = locations.pop() ) {
|
||||
// rhill 2013-12-09:
|
||||
// Ignore list if disabled
|
||||
// https://github.com/gorhill/httpswitchboard/issues/78
|
||||
if ( storedLists[location].off ) {
|
||||
if ( lists[location].off ) {
|
||||
blacklistLoadCount -= 1;
|
||||
continue;
|
||||
}
|
||||
µb.assets.get(location, mergeBlacklist);
|
||||
}
|
||||
};
|
||||
|
||||
var onListOfBlockListsLoaded = function(details) {
|
||||
var µb = µBlock;
|
||||
// Initialize built-in list of 3rd-party block lists.
|
||||
var lists = JSON.parse(details.content);
|
||||
for ( var location in lists ) {
|
||||
if ( lists.hasOwnProperty(location) === false ) {
|
||||
continue;
|
||||
if ( /^https?:\/\/.+$/.test(location) ) {
|
||||
µb.assets.getExternal(location, mergeBlacklist);
|
||||
} else {
|
||||
µb.assets.get(location, mergeBlacklist);
|
||||
}
|
||||
µb.remoteBlacklists['assets/thirdparties/' + location] = lists[location];
|
||||
}
|
||||
// Now get user's selection of list of block lists.
|
||||
chrome.storage.local.get(
|
||||
{ 'remoteBlacklists': µb.remoteBlacklists },
|
||||
loadBlacklistsStart
|
||||
);
|
||||
};
|
||||
|
||||
// Reset list of 3rd-party block lists.
|
||||
for ( var location in this.remoteBlacklists ) {
|
||||
if ( location.indexOf('assets/thirdparties/') === 0 ) {
|
||||
delete this.remoteBlacklists[location];
|
||||
}
|
||||
}
|
||||
|
||||
// Get new list of 3rd-party block lists.
|
||||
this.assets.get('assets/ublock/filter-lists.json', onListOfBlockListsLoaded);
|
||||
this.getAvailableLists(loadBlacklistsStart);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
Loading…
Reference in New Issue