1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-07-08 12:57:57 +02:00

this fixes #138, next: thorough code review

This commit is contained in:
gorhill 2014-08-19 20:41:52 -04:00
parent 56ed6b9f4e
commit 1deae3bfe0
20 changed files with 943 additions and 842 deletions

View File

@ -36,18 +36,59 @@ ul > li > ul > li {
.dim {
color: #888;
}
button.purge {
/* I designed the button with: http://charliepark.org/bootstrap_buttons/ */
button.reloadAll {
border: 1px solid transparent;
border-radius: 3px;
border-color: #dddddd #dddddd hsl(36, 0%, 85%);
padding: 5px;
background-color: hsl(36, 0%, 72%) !important;
background-repeat: repeat-x;
background-image: linear-gradient(#f2f2f2, #dddddd);
color: #aaa;
}
button.reloadAll.enabled {
border-color: #ffcc7f #ffcc7f hsl(36, 100%, 73%);
color: #222;
background-color: hsl(36, 100%, 75%) !important;
background-image: linear-gradient(#ffdca8, #ffcc7f);
cursor: pointer;
opacity: 0.8;
}
button.reloadAll:hover {
opacity: 1.0;
}
#buttonApply {
display: none;
position: fixed;
right: 1em;
top: 1em;
}
#buttonApply.enabled {
display: initial;
}
span.status {
margin: 0;
border: 1px solid #ccc;
border: 1px solid transparent;
padding: 1px 2px;
display: inline-block;
font-size: 11px;
opacity: 0.7;
}
span.purge {
border-color: #ddd;
color: #444;
background-color: #eee;
font-size: 11px;
opacity: 0.6;
cursor: pointer;
}
button.purge:hover {
span.purge:hover {
opacity: 1;
}
span.obsolete {
border-color: hsl(36, 100%, 73%);
color: #222;
background-color: hsl(36, 100%, 75%);
}
#externalLists {
font-size: smaller;
width: 48em;
@ -59,10 +100,11 @@ button.purge:hover {
<body>
<button id="buttonApply" class="reloadAll" data-i18n="3pApplyChanges"></button>
<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>
<li><input type="checkbox" id="autoUpdate"><label data-i18n="3pAutoUpdatePrompt1"></label>
<button class="reloadAll" id="buttonUpdate" data-i18n="3pUpdateNow"></button>
<li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1"></label>
<button class="whatisthis"></button>
<div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div>
<li style="margin-top:0.75em"><p id="listsOfBlockedHostsPrompt"></p>

View File

@ -99,13 +99,17 @@
"message":"{{used}} benutzt aus {{total}}",
"description":"English: {{used}} used out of {{total}}"
},
"3pAutoUpdatePrompt1":{
"message":"Auto-update filter lists.",
"description":"English: Auto-update filter lists."
},
"3pUpdateNow":{
"message":"Update now",
"description":"English: Update now"
},
"3pParseAllABPHideFiltersPrompt1":{
"message":"Adblock+ Filter zum Verstecken von Elementen analysieren und anwenden.",
"description":"English: Parse and enforce Adblock+ element hiding filters."
},
"3pParseAllABPHideFiltersPrompt2":{
"message":"{{abpHideFilterCount}} Filter zum Verstecken von Elementen genutzt.",
"description":"English: {{abpHideFilterCount}} element hiding filters used."
"description":"English: Parse and enforce cosmetic filters."
},
"3pParseAllABPHideFiltersInfo":{
"message":"<p>Diese Option ermöglicht die Analyse und Anwendung von <a href=\"https:\/\/adblockplus.org\/de\/faq_internal#elemhide\">Adblock Plus-kompatiblen Filtern zum &ldquo;Verstecken von Elementen&rdquo; <\/a>. Diese Filter sind in erster Linie kosmetischer Natur und dienen zum Verstecken von Elementen auf einer Webseite, die als optische Belästigung wahrgenommen werden und nicht von den vorhandenen Filtern geblockt werden können.<\/p><p>Das Aktivieren dieser Option erhöht den Speicherbedarf von <i>µBlock<\/i>.<\/p>",
@ -159,6 +163,14 @@
"message":"Leere den Cache",
"description":"English: purge cache"
},
"3pExternalListNew":{
"message":"new version available",
"description":"English: new version available"
},
"3pExternalListObsolete":{
"message":"may be obsolete",
"description":"English: may be obsolete"
},
"1pFormatHint":{
"message":"Eine Regel pro Zeile. Eine Regel kann ein einfacher Host-Name sein oder ein Adblock Plus-kompatibler Filter. Zeilen mit vorangestelltem &lsquo;!&rsquo; werden ignoriert.",
"description":"English: One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with &lsquo;!&rsquo; will be ignored."

View File

@ -99,13 +99,17 @@
"message":"{{used}} used out of {{total}}",
"description":"English: {{used}} used out of {{total}}"
},
"3pParseAllABPHideFiltersPrompt1":{
"message":"Parse and enforce Adblock+ element hiding filters.",
"description":"English: Parse and enforce Adblock+ element hiding filters."
"3pAutoUpdatePrompt1":{
"message":"Auto-update filter lists.",
"description":"English: Auto-update filter lists."
},
"3pParseAllABPHideFiltersPrompt2":{
"message":"{{abpHideFilterCount}} element hiding filters used.",
"description":"English: {{abpHideFilterCount}} element hiding filters used."
"3pUpdateNow":{
"message":"Update now",
"description":"English: Update now"
},
"3pParseAllABPHideFiltersPrompt1":{
"message":"Parse and enforce cosmetic filters.",
"description":"English: Parse and enforce Adblock+ element hiding filters."
},
"3pParseAllABPHideFiltersInfo":{
"message":"<p>This option enables the parsing and enforcing of <a href=\"https:\/\/adblockplus.org\/en\/faq_internal#elemhide\">Adblock Plus-compatible &ldquo;element hiding&rdquo; filters<\/a>. These filters are essentially cosmetic, they serve to hide elements in a web page which are deemed to be a visual nuisance, and which can't be blocked by the net request-based filtering engine.<\/p><p>Enabling this feature increases <i>µBlock<\/i>'s memory footprint.<\/p>",
@ -159,6 +163,14 @@
"message":"purge cache",
"description":"English: purge cache"
},
"3pExternalListNew":{
"message":"new version available",
"description":"English: new version available"
},
"3pExternalListObsolete":{
"message":"may be obsolete",
"description":"English: may be obsolete"
},
"1pFormatHint":{
"message":"One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with &lsquo;!&rsquo; 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 &lsquo;!&rsquo; will be ignored."

View File

@ -99,13 +99,17 @@
"message":"{{used}} utilisé(s) sur un total de {{total}}",
"description":"English: {{used}} used out of {{total}}"
},
"3pParseAllABPHideFiltersPrompt1":{
"message":"Utiliser en plus les règles Adblock Plus esthétiques",
"description":"English: Parse and enforce Adblock+ element hiding filters."
"3pAutoUpdatePrompt1":{
"message":"Mise à jour automatique des listes",
"description":"English: Auto-update filter lists."
},
"3pParseAllABPHideFiltersPrompt2":{
"message":"{{abpHideFilterCount}} règle(s) Adblock Plus esthétique(s) utilisée(s)",
"description":"English: {{abpHideFilterCount}} element hiding filters used."
"3pUpdateNow":{
"message":"Mettre à jour",
"description":"English: Update now"
},
"3pParseAllABPHideFiltersPrompt1":{
"message":"Utiliser en plus les règles esthétiques",
"description":"English: Parse and enforce cosmetic filters."
},
"3pParseAllABPHideFiltersInfo":{
"message":"<p>Cette option permet de prendre en charge les filtres AdblockPlus de type <a href=\"https:\/\/adblockplus.org\/en\/faq_internal#elemhide\">&ldquo;element hiding&rdquo;<\/a>. Ces filtres ont principalement un impact visuel, servant à dissimuler des éléments nuisibles d'une page Web et qui ne sont pas blocables par le filtrage standard.<\/p><p>L'activation de cette fonctionnalité augmente l'empreinte mémoire de <i>µBlock<\/i><\/p>",
@ -159,6 +163,14 @@
"message":"vider le cache",
"description":"English: purge cache"
},
"3pExternalListNew":{
"message":"nouvelle version disponible",
"description":"English: new version available"
},
"3pExternalListObsolete":{
"message":"potentiellement désuet",
"description":"English: may be obsolete"
},
"1pFormatHint":{
"message":"Une règle par ligne. Une règle peut être un simple nom d'hôte, ou encore un filtre respectant la syntaxe des filtres Adblock Plus. Les lignes débutant par &lsquo;!&rsquo; seront ignorées.",
"description":"English: One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with &lsquo;!&rsquo; will be ignored."

View File

@ -6,46 +6,8 @@
<link rel="stylesheet" type="text/css" href="css/common.css">
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css">
<style>
table th {
text-align: left;
}
table td:first-child {
padding-right: 2em;
}
#allLocalAssetsUpdated {
margin-left: 1em;
color: green;
}
#assetList table tr.unchanged {
color: gray;
}
#assetList table tr td:nth-of-type(2) {
font-weight: bold;
white-space: nowrap;
}
#assetList table tr.unchanged td:nth-of-type(2) {
font-weight: normal;
}
#assetList.ooo > table {
display: none;
}
#assetList.oox > table,
#assetList.oxx > table,
#assetList.xxx > table {
display: block;
}
#assetList > p {
display: none;
}
#assetList.ooo > p.ooo {
display: block;
}
#assetList.oxx > p.oxx {
display: block;
}
#assetList.xxx > p.xxx {
display: block;
ul {
padding-left: 1em;
}
</style>
</head>
@ -53,38 +15,14 @@ table td:first-child {
<body>
<h2>µBlock <span id="aboutVersion"></span></h2>
<div>
<a href="https://github.com/gorhill/uBlock/releases" data-i18n="aboutChangelog"></a><br>
<a href="https://github.com/gorhill/ublock" data-i18n="aboutCode"></a><br>
</div>
<h2 data-i18n="aboutExtensionDataHeader"></h2>
<div>
<p class="para" data-i18n="aboutAssetsUpdatePrompt"></p>
<div id="assetList">
<!--
Let's define 'abc' as bit 0 to 2
Where bit can be '0' or '1'
Bit 0: list => o=absent, x=present
Bit 1: list => o=clean, x=dirty
Bit 2: update => o=idle, x=updating
Therefore:
List visible: oox oxx xox
Etc.
-->
<table class="ooo">
<tr><th data-i18n="aboutAssetsUpdateColPath"><th data-i18n="aboutAssetsUpdateColStatus">
</table>
<p class="ooo" style="color:red" data-i18n="aboutAssetsUpdateGetListError"></p>
<p class="oxx"><button type="button" id="aboutAssetsUpdateButton" data-i18n="aboutAssetsUpdateButton"></button></p>
<p class="xxx"><button type="button" disabled data-i18n="aboutAssetsUpdatingButton"></button></p>
</div>
</div>
<ul>
<li><a href="https://github.com/gorhill/uBlock/releases" data-i18n="aboutChangelog"></a><br>
<li><a href="https://github.com/gorhill/ublock" data-i18n="aboutCode"></a><br>
</ul>
<script src="js/udom.js"></script>
<script src="js/i18n.js"></script>
<script src="js/dashboard-common.js"></script>
<script src="js/messaging-client.js"></script>
<script src="js/about.js"></script>
</body>

View File

@ -1 +0,0 @@
# your custom filters

View File

@ -13,7 +13,6 @@
<script src="js/liquid-dict.js"></script>
<script src="js/utils.js"></script>
<script src="js/assets.js"></script>
<script src="js/asset-updater.js"></script>
<script src="js/abp-filters.js"></script>
<script src="js/abp-hide-filters.js"></script>
<script src="js/ublock.js"></script>

View File

@ -31,6 +31,7 @@ var userListName = chrome.i18n.getMessage('1pPageName');
var listDetails = {};
var externalLists = '';
var cacheWasPurged = false;
var needUpdate = false;
/******************************************************************************/
@ -40,7 +41,6 @@ var onMessage = function(msg) {
switch ( msg.what ) {
case 'loadUbiquitousBlacklistCompleted':
renderBlacklists();
selectedBlacklistsChanged();
break;
default:
@ -109,6 +109,8 @@ var renderBlacklists = function() {
var listStatsTemplate = chrome.i18n.getMessage('3pListsOfBlockedHostsPerListStats');
var purgeButtontext = chrome.i18n.getMessage('3pExternalListPurge');
var updateButtontext = chrome.i18n.getMessage('3pExternalListNew');
var obsoleteButtontext = chrome.i18n.getMessage('3pExternalListObsolete');
var htmlFromBranch = function(groupKey, listKeys, lists) {
var html = [
@ -134,7 +136,7 @@ var renderBlacklists = function() {
listStatsTemplate,
'</span>'
].join('');
var listKey, list, listEntry;
var listKey, list, listEntry, entryDetails;
for ( var i = 0; i < listKeys.length; i++ ) {
listKey = listKeys[i];
list = lists[listKey];
@ -146,12 +148,27 @@ var renderBlacklists = function() {
.replace('{{total}}', !isNaN(+list.entryCount) ? renderNumber(list.entryCount) : '?');
html.push(listEntry);
// https://github.com/gorhill/uBlock/issues/104
if ( /^https?:\/\/.+/.test(listKey) && listDetails.cache[listKey] ) {
entryDetails = listDetails.cache[listKey];
if ( entryDetails === undefined ) {
continue;
}
// Update status
if ( !list.off && (entryDetails.repoObsolete || entryDetails.cacheObsolete) ) {
html.push(
'&ensp;',
'<button type="button" class="purge">',
'<span class="status obsolete">',
entryDetails.repoObsolete ? updateButtontext : obsoleteButtontext,
'</span>'
);
needUpdate = true;
}
// In cache
else if ( entryDetails.cached ) {
html.push(
'&ensp;',
'<span class="status purge">',
purgeButtontext,
'</button>'
'</span>'
);
}
}
@ -159,6 +176,8 @@ var renderBlacklists = function() {
return html.join('');
};
// https://www.youtube.com/watch?v=unCVi4hYRlY#t=30m18s
var groupsFromLists = function(lists) {
var groups = {};
var listKeys = Object.keys(lists);
@ -178,6 +197,7 @@ var renderBlacklists = function() {
var onListsReceived = function(details) {
listDetails = details;
needUpdate = false;
var lists = details.available;
var html = [];
@ -208,13 +228,10 @@ var renderBlacklists = function() {
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('#autoUpdate').prop('checked', listDetails.autoUpdate === true);
uDom('#parseCosmeticFilters').prop('checked', listDetails.cosmetic === true);
uDom('a').attr('target', '_blank');
selectedBlacklistsChanged();
updateApplyButtons();
};
messaging.ask({ what: 'getLists' }, onListsReceived);
@ -222,9 +239,9 @@ var renderBlacklists = function() {
/******************************************************************************/
// Check whether lists need reloading.
// Return whether selection of lists changed.
var needToReload = function() {
var listsSelectionChanged = function() {
if ( listDetails.cosmetic !== getµb().userSettings.parseAllABPHideFilters ) {
return true;
}
@ -261,10 +278,19 @@ var needToReload = function() {
/******************************************************************************/
// Return whether content need update.
var listsContentChanged = function() {
return needUpdate;
};
/******************************************************************************/
// This is to give a visual hint that the selection of blacklists has changed.
var selectedBlacklistsChanged = function() {
uDom('#blacklistsApply').prop('disabled', !needToReload());
var updateApplyButtons = function() {
uDom('#buttonApply').toggleClass('enabled', listsSelectionChanged());
uDom('#buttonUpdate').toggleClass('enabled', listsContentChanged());
};
/******************************************************************************/
@ -278,7 +304,7 @@ var onListCheckboxChanged = function() {
return;
}
listDetails.available[href].off = !this.checked;
selectedBlacklistsChanged();
updateApplyButtons();
};
/******************************************************************************/
@ -295,22 +321,22 @@ var onListLinkClicked = function(ev) {
var onPurgeClicked = function(ev) {
var button = uDom(this);
var href = button.parent().find('a').first().attr('href');
var li = button.parent();
var href = li.find('a').first().attr('href');
if ( !href ) {
return;
}
messaging.tell({ what: 'purgeCache', path: href });
button.remove();
cacheWasPurged = true;
selectedBlacklistsChanged();
if ( li.find('input').first().prop('checked') ) {
cacheWasPurged = true;
updateApplyButtons();
}
};
/******************************************************************************/
var blacklistsApplyHandler = function() {
if ( !needToReload() ) {
return;
}
var reloadAll = function(update) {
// Reload blacklists
messaging.tell({
what: 'userSettings',
@ -334,17 +360,40 @@ var blacklistsApplyHandler = function() {
}
messaging.tell({
what: 'reloadAllFilters',
switches: switches
switches: switches,
update: update
});
cacheWasPurged = false;
uDom('#blacklistsApply').prop('disabled', true);
};
/******************************************************************************/
var buttonApplyHandler = function() {
reloadAll();
uDom('#buttonApply').toggleClass('enabled', false);
};
/******************************************************************************/
var buttonUpdateHandler = function() {
reloadAll(true);
};
/******************************************************************************/
var autoUpdateCheckboxChanged = function() {
messaging.tell({
what: 'userSettings',
name: 'autoUpdate',
value: this.checked
});
};
/******************************************************************************/
var abpHideFiltersCheckboxChanged = function() {
listDetails.cosmetic = this.checked;
selectedBlacklistsChanged();
updateApplyButtons();
};
/******************************************************************************/
@ -383,11 +432,13 @@ var externalListsApplyHandler = function() {
uDom.onLoad(function() {
// Handle user interaction
uDom('#parseAllABPHideFilters').on('change', abpHideFiltersCheckboxChanged);
uDom('#blacklistsApply').on('click', blacklistsApplyHandler);
uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged);
uDom('#parseCosmeticFilters').on('change', abpHideFiltersCheckboxChanged);
uDom('#buttonApply').on('click', buttonApplyHandler);
uDom('#buttonUpdate').on('click', buttonUpdateHandler);
uDom('#lists').on('change', '.listDetails > input', onListCheckboxChanged);
uDom('#lists').on('click', '.listDetails > a:nth-of-type(1)', onListLinkClicked);
uDom('#lists').on('click', 'button.purge', onPurgeClicked);
uDom('#lists').on('click', 'span.purge', onPurgeClicked);
uDom('#externalLists').on('input', externalListsChangeHandler);
uDom('#externalListsApply').on('click', externalListsApplyHandler);

View File

@ -27,95 +27,7 @@ uDom.onLoad(function() {
/******************************************************************************/
var updateList = {};
var assetListSwitches = ['o', 'o', 'o'];
var commitHistoryURLPrefix = 'https://github.com/gorhill/ublock/commits/master/';
/******************************************************************************/
var setAssetListClassBit = function(bit, state) {
assetListSwitches[assetListSwitches.length-1-bit] = !state ? 'o' : 'x';
uDom('#assetList')
.removeClass()
.addClass(assetListSwitches.join(''));
};
/******************************************************************************/
var renderAssetList = function(details) {
var dirty = false;
var paths = Object.keys(details.list).sort();
if ( paths.length > 0 ) {
uDom('#assetList .assetEntry').remove();
var i = 0;
var path, status, html = [];
while ( path = paths[i++] ) {
status = details.list[path].status;
dirty = dirty || status !== 'Unchanged';
html.push(
'<tr class="assetEntry ' + status.toLowerCase().replace(/ +/g, '-') + '">',
'<td>',
'<a href="' + commitHistoryURLPrefix + path + '">',
path.replace(/^(assets\/[^/]+\/)(.+)$/, '$1<b>$2</b>'),
'</a>',
'<td>',
chrome.i18n.getMessage('aboutAssetsUpdateStatus' + status)
);
}
uDom('#assetList table tBody').append(html.join(''));
uDom('#assetList a').attr('target', '_blank');
updateList = details.list;
}
setAssetListClassBit(0, paths.length !== 0);
setAssetListClassBit(1, dirty);
setAssetListClassBit(2, false);
};
/******************************************************************************/
var updateAssets = function() {
setAssetListClassBit(2, true);
var onDone = function(details) {
if ( details.changedCount !== 0 ) {
messaging.tell({ what: 'loadUpdatableAssets' });
}
};
messaging.ask({ what: 'launchAssetUpdater', list: updateList }, onDone);
};
/******************************************************************************/
var updateAssetsList = function() {
messaging.ask({ what: 'getAssetUpdaterList' }, renderAssetList);
};
/******************************************************************************/
// Updating all assets could be done from elsewhere and if so the
// list here needs to be updated.
var onAnnounce = function(msg) {
switch ( msg.what ) {
case 'allLocalAssetsUpdated':
updateAssetsList();
break;
default:
break;
}
};
messaging.start('about.js');
messaging.listen(onAnnounce);
/******************************************************************************/
uDom('#aboutVersion').html(chrome.runtime.getManifest().version);
uDom('#aboutAssetsUpdateButton').on('click', updateAssets);
/******************************************************************************/
updateAssetsList();
/******************************************************************************/

View File

@ -1,227 +0,0 @@
/*******************************************************************************
µBlock - a Chromium browser extension to block requests.
Copyright (C) 2014 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/uBlock
*/
/* global chrome, µBlock */
/******************************************************************************/
// Asset update manager
µBlock.assetUpdater = (function() {
/******************************************************************************/
var getUpdateList = function(callback) {
var localChecksumsText = '';
var remoteChecksumsText = '';
var compareChecksums = function() {
var parseChecksumsText = function(text) {
var result = {};
var lines = text.split(/\n+/);
var i = lines.length;
var fields;
while ( i-- ) {
fields = lines[i].trim().split(/\s+/);
if ( fields.length !== 2 ) {
continue;
}
result[fields[1]] = fields[0];
}
return result;
};
if ( remoteChecksumsText === 'Error' || localChecksumsText === 'Error' ) {
remoteChecksumsText = localChecksumsText = '';
}
var localAssetChecksums = parseChecksumsText(localChecksumsText);
var remoteAssetChecksums = parseChecksumsText(remoteChecksumsText);
var toUpdate = {};
var path;
for ( path in remoteAssetChecksums ) {
if ( !remoteAssetChecksums.hasOwnProperty(path) ) {
continue;
}
if ( localAssetChecksums[path] === undefined ) {
toUpdate[path] = {
status: 'Added',
remoteChecksum: remoteAssetChecksums[path],
localChecksum: ''
};
continue;
}
if ( localAssetChecksums[path] === remoteAssetChecksums[path] ) {
toUpdate[path] = {
status: 'Unchanged',
remoteChecksum: remoteAssetChecksums[path],
localChecksum: localAssetChecksums[path]
};
continue;
}
toUpdate[path] = {
status: 'Changed',
remoteChecksum: remoteAssetChecksums[path],
localChecksum: localAssetChecksums[path]
};
}
for ( path in localAssetChecksums ) {
if ( !localAssetChecksums.hasOwnProperty(path) ) {
continue;
}
if ( remoteAssetChecksums[path] === undefined ) {
toUpdate[path] = {
status: 'Removed',
remoteChecksum: '',
localChecksum: localAssetChecksums[path]
};
}
}
callback({ 'list': toUpdate });
};
var validateChecksums = function(details) {
if ( details.error || details.content === '' ) {
return 'Error';
}
if ( /^(?:[0-9a-f]{32}\s+\S+(\s+|$))+/.test(details.content) ) {
return details.content;
}
return 'Error';
};
var onLocalChecksumsLoaded = function(details) {
localChecksumsText = validateChecksums(details);
if ( remoteChecksumsText !== '' ) {
compareChecksums();
}
};
var onRemoteChecksumsLoaded = function(details) {
remoteChecksumsText = validateChecksums(details);
if ( localChecksumsText !== '' ) {
compareChecksums();
}
};
µBlock.assets.getRepo('assets/checksums.txt', onRemoteChecksumsLoaded);
µBlock.assets.get('assets/checksums.txt', onLocalChecksumsLoaded);
};
/******************************************************************************/
// If `list` is null, it will be fetched internally.
var update = function(list, callback) {
var assetChangedCount = 0;
var assetProcessedCount;
var updatedAssetChecksums = [];
var onCompleted = function() {
var details = {
what: 'allLocalAssetsUpdated',
changedCount: assetChangedCount
};
callback(details);
µBlock.messaging.announce(details);
};
var doCountdown = function() {
assetProcessedCount -= 1;
if ( assetProcessedCount > 0 ) {
return;
}
µBlock.assets.put(
'assets/checksums.txt',
updatedAssetChecksums.join('\n'),
onCompleted
);
chrome.storage.local.set({ 'assetsUpdateTimestamp': Date.now() });
};
var assetUpdated = function(details) {
var path = details.path;
var entry = list[path];
if ( details.error ) {
updatedAssetChecksums.push(entry.localChecksum + ' ' + path);
} else {
updatedAssetChecksums.push(entry.remoteChecksum + ' ' + path);
assetChangedCount += 1;
}
doCountdown();
};
var processList = function() {
assetProcessedCount = Object.keys(list).length;
if ( assetProcessedCount === 0 ) {
onCompleted();
return;
}
var entry;
var details = { path: '', md5: '' };
for ( var path in list ) {
if ( list.hasOwnProperty(path) === false ) {
continue;
}
entry = list[path];
if ( entry.status === 'Added' || entry.status === 'Changed' ) {
details.path = path;
details.md5 = entry.remoteChecksum;
µBlock.assets.update(details, assetUpdated);
continue;
}
if ( entry.status === 'Unchanged' ) {
updatedAssetChecksums.push(entry.localChecksum + ' ' + path);
}
doCountdown();
}
};
var listLoaded = function(details) {
list = details.list;
processList();
};
// Purge obsolete external assets
µBlock.assets.purge(/^https?:\/\/.+$/, Date.now() - µBlock.updateAssetsEvery);
if ( list ) {
processList();
} else {
getUpdateList(listLoaded);
}
};
/******************************************************************************/
// Export API
return {
'getList': getUpdateList,
'update': update
};
/******************************************************************************/
})();
/******************************************************************************/

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@ return {
manifest: chrome.runtime.getManifest(),
userSettings: {
autoUpdate: true,
collapseBlocked: true,
externalLists: '',
logBlockedRequests: false,

View File

@ -250,9 +250,10 @@ var getLists = function(callback) {
available: null,
current: µb.remoteBlacklists,
cosmetic: µb.userSettings.parseAllABPHideFilters,
autoUpdate: µb.userSettings.autoUpdate,
cache: null
};
var onEntries = function(entries) {
var onMetadataReady = function(entries) {
r.cache = entries;
if ( r.available ) {
callback(r);
@ -265,7 +266,7 @@ var getLists = function(callback) {
}
};
µb.getAvailableLists(onLists);
µb.assets.entries(onEntries);
µb.assets.metadata(onMetadataReady);
};
/******************************************************************************/
@ -475,20 +476,6 @@ var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
case 'getAssetUpdaterList':
return µb.assetUpdater.getList(callback);
case 'launchAssetUpdater':
return µb.assetUpdater.update(request.list, callback);
case 'readUserSettings':
return chrome.storage.local.get(µb.userSettings, callback);
case 'readUserFilters':
return µb.assets.get(µb.userFiltersPath, callback);
case 'writeUserFilters':
return µb.assets.put(µb.userFiltersPath, request.content, callback);
default:
break;
@ -498,20 +485,6 @@ var onMessage = function(request, sender, callback) {
var response;
switch ( request.what ) {
case 'loadUpdatableAssets':
response = µb.loadUpdatableAssets();
break;
case 'readFilterListSelection':
response = µb.remoteBlacklists;
break;
case 'getSomeStats':
response = {
storageQuota: µb.storageQuota,
storageUsed: µb.storageUsed
};
break;
default:
return µb.messaging.defaultHandler(request, sender, callback);
@ -524,4 +497,6 @@ var onMessage = function(request, sender, callback) {
})();
// https://www.youtube.com/watch?v=3_WcygKJP1k
/******************************************************************************/

View File

@ -132,15 +132,12 @@ var onMessage = function(request, port) {
/******************************************************************************/
// Default is for commonly used message.
// Default is for commonly used messages.
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':
@ -171,7 +168,7 @@ function defaultHandler(request, sender, callback) {
break;
case 'reloadAllFilters':
µBlock.reloadPresetBlacklists(request.switches);
µBlock.reloadPresetBlacklists(request.switches, request.update);
break;
case 'userSettings':
@ -186,6 +183,8 @@ function defaultHandler(request, sender, callback) {
callback(response);
}
// https://www.youtube.com/watch?v=rrzRgUAHqc8
/******************************************************************************/
// Port disconnected, relay this information to apropriate listener.

View File

@ -218,7 +218,7 @@ PageStore.prototype.updateBadgeFromTab = function(tab) {
var iconStr = '';
if ( µb.userSettings.showIconBadge && netFiltering && this.perLoadBlockedRequestCount ) {
iconStr = this.perLoadBlockedRequestCount.toLocaleString();
iconStr = µb.utils.formatCount(this.perLoadBlockedRequestCount);
}
chrome.browserAction.setBadgeText({ tabId: tab.id, text: iconStr });
@ -234,6 +234,8 @@ PageStore.prototype.updateBadge = function() {
chrome.tabs.get(this.tabId, this.updateBadgeFromTab.bind(this));
};
// https://www.youtube.com/watch?v=drW8p_dTLD4
/******************************************************************************/
return {

View File

@ -35,18 +35,17 @@
(function() {
var µb = µBlock;
var jobDone = function(details) {
if ( details.changedCount === 0 ) {
var jobCallback = function() {
if ( µb.userSettings.autoUpdate !== true ) {
return;
}
µb.loadUpdatableAssets();
};
var jobCallback = function() {
µb.assetUpdater.update(null, jobDone);
// TODO: need smarter update, currently blindly reloading all.
µb.loadUpdatableAssets(true);
};
µb.asyncJobs.add('autoUpdateAssets', null, jobCallback, µb.updateAssetsEvery, true);
})();
// https://www.youtube.com/watch?v=cIrGQD84F1g
/******************************************************************************/

View File

@ -70,7 +70,7 @@
/******************************************************************************/
µBlock.loadUserSettings = function() {
µBlock.loadUserSettings = function(callback) {
var settingsLoaded = function(store) {
var µb = µBlock;
// Backward compatibility after fix to #5
@ -88,6 +88,8 @@
µb.userSettings = store;
µb.netWhitelist = µb.whitelistFromString(store.netWhitelist);
µb.netWhitelistModifyTime = Date.now();
callback();
};
chrome.storage.local.get(this.userSettings, settingsLoaded);
@ -265,11 +267,7 @@
blacklistLoadCount -= 1;
continue;
}
if ( /^https?:\/\/.+$/.test(location) ) {
µb.assets.getExternal(location, mergeBlacklist);
} else {
µb.assets.get(location, mergeBlacklist);
}
µb.assets.get(location, mergeBlacklist);
}
};
@ -400,7 +398,7 @@
// `switches` contains the preset blacklists for which the switch must be
// revisited.
µBlock.reloadPresetBlacklists = function(switches) {
µBlock.reloadPresetBlacklists = function(switches, update) {
var presetBlacklists = this.remoteBlacklists;
// Toggle switches, if any
@ -420,7 +418,7 @@
}
// Now force reload
this.loadUbiquitousBlacklists();
this.loadUpdatableAssets(update);
};
/******************************************************************************/
@ -443,9 +441,11 @@
// Load updatable assets
µBlock.loadUpdatableAssets = function() {
this.loadUbiquitousBlacklists();
µBlock.loadUpdatableAssets = function(update) {
this.assets.autoUpdate = update;
this.assets.autoUpdateDelay = this.updateAssetsEvery;
this.loadPublicSuffixList();
this.loadUbiquitousBlacklists();
};
/******************************************************************************/
@ -453,11 +453,8 @@
// Load all
µBlock.load = function() {
this.loadLocalSettings();
this.loadUserSettings();
// load updatable assets -- after updating them if needed
this.assetUpdater.update(null, this.loadUpdatableAssets.bind(this));
// User settings need to be available for this because we need
// µBlock.userSettings.externalLists
this.loadUserSettings(this.loadUpdatableAssets.bind(this, this.userSettings.autoUpdate));
this.getBytesInUse();
};

View File

@ -233,24 +233,3 @@
};
/******************************************************************************/
µBlock.formatCount = function(count) {
if ( typeof count !== 'number' ) {
return '';
}
var s = count.toFixed(0);
if ( count >= 1000 ) {
if ( count < 10000 ) {
s = '>' + s.slice(0,1) + 'K';
} else if ( count < 100000 ) {
s = s.slice(0,2) + 'K';
} else if ( count < 1000000 ) {
s = s.slice(0,3) + 'K';
} else if ( count < 10000000 ) {
s = s.slice(0,1) + 'M';
} else {
s = s.slice(0,-6) + 'M';
}
}
return s;
};

View File

@ -29,7 +29,11 @@
/******************************************************************************/
var gotoURL = function(details) {
var exports = {};
/******************************************************************************/
exports.gotoURL = function(details) {
if ( details.tabId ) {
chrome.tabs.update(details.tabId, { url: details.url });
} else {
@ -39,7 +43,7 @@ var gotoURL = function(details) {
/******************************************************************************/
var gotoExtensionURL = function(url) {
exports.gotoExtensionURL = function(url) {
var hasQuery = function(url) {
return url.indexOf('?') >= 0;
@ -98,11 +102,33 @@ var gotoExtensionURL = function(url) {
/******************************************************************************/
return {
gotoURL: gotoURL,
gotoExtensionURL: gotoExtensionURL
exports.formatCount = function(count) {
if ( typeof count !== 'number' ) {
return '';
}
var s = count.toFixed(0);
if ( count >= 1000 ) {
if ( count < 10000 ) {
s = '>' + s.slice(0,1) + 'K';
} else if ( count < 100000 ) {
s = s.slice(0,2) + 'K';
} else if ( count < 1000000 ) {
s = s.slice(0,3) + 'K';
} else if ( count < 10000000 ) {
s = s.slice(0,1) + 'M';
} else {
s = s.slice(0,-6) + 'M';
}
}
return s;
};
// https://www.youtube.com/watch?v=uvUW4ozs7pY
/******************************************************************************/
return exports;
/******************************************************************************/
})();

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "__MSG_extName__",
"short_name": "µBlock",
"version": "0.4.0.1",
"version": "0.4.0.2",
"description": "__MSG_extShortDesc__",
"icons": {
"16": "img/icon_16.png",