diff --git a/3p-filters.html b/3p-filters.html
index 3d044dc16..d8cbb3c47 100644
--- a/3p-filters.html
+++ b/3p-filters.html
@@ -14,6 +14,7 @@
-
+
-
diff --git a/_locales/de/messages.json b/_locales/de/messages.json
index d5846a3aa..eb4a764f0 100644
--- a/_locales/de/messages.json
+++ b/_locales/de/messages.json
@@ -107,6 +107,10 @@
"message":"Jetzt aktualisieren",
"description":"English: Update now"
},
+ "3pPurgeAll":{
+ "message":"Purge all caches",
+ "description":"English: Purge all caches"
+ },
"3pParseAllABPHideFiltersPrompt1":{
"message":"Adblock+ Filter zum Verstecken von Elementen analysieren und anwenden.",
"description":"English: Parse and enforce cosmetic filters."
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index a3d07184b..dd3e332b5 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -107,6 +107,10 @@
"message":"Update now",
"description":"English: Update now"
},
+ "3pPurgeAll":{
+ "message":"Purge all caches",
+ "description":"English: Purge all caches"
+ },
"3pParseAllABPHideFiltersPrompt1":{
"message":"Parse and enforce cosmetic filters.",
"description":"English: Parse and enforce Adblock+ element hiding filters."
diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json
index 2c1bc6423..3e1e30cfc 100644
--- a/_locales/fr/messages.json
+++ b/_locales/fr/messages.json
@@ -107,6 +107,10 @@
"message":"Mettre à jour",
"description":"English: Update now"
},
+ "3pPurgeAll":{
+ "message":"Vider tous les caches",
+ "description":"English: Purge all caches"
+ },
"3pParseAllABPHideFiltersPrompt1":{
"message":"Utiliser en plus les règles esthétiques",
"description":"English: Parse and enforce cosmetic filters."
diff --git a/css/3p-filters.css b/css/3p-filters.css
index 90e7e60f3..8c2379a36 100644
--- a/css/3p-filters.css
+++ b/css/3p-filters.css
@@ -33,7 +33,7 @@ li.listDetails > a:nth-of-type(2) {
opacity: 0.5;
}
/* I designed the button with: http://charliepark.org/bootstrap_buttons/ */
-button.reloadAll {
+button {
border: 1px solid transparent;
border-radius: 3px;
border-color: #dddddd #dddddd hsl(36, 0%, 85%);
@@ -43,15 +43,20 @@ button.reloadAll {
background-image: linear-gradient(#f2f2f2, #dddddd);
color: #aaa;
}
-button.reloadAll.enabled {
- border-color: #ffcc7f #ffcc7f hsl(36, 100%, 73%);
+button.enabled {
+ border-color: #80b3ff #80b3ff hsl(216, 100%, 75%);
+ background-color: hsl(216, 100%, 75%);
+ background-image: linear-gradient(#a8cbff, #80b3ff);
color: #222;
- background-color: hsl(36, 100%, 75%);
- background-image: linear-gradient(#ffdca8, #ffcc7f);
cursor: pointer;
opacity: 0.8;
}
-button.reloadAll:hover {
+button.reloadAll.enabled {
+ border-color: #ffcc7f #ffcc7f hsl(36, 100%, 73%);
+ background-color: hsl(36, 100%, 75%);
+ background-image: linear-gradient(#ffdca8, #ffcc7f);
+ }
+button.enabled:hover {
opacity: 1.0;
}
#buttonApply {
diff --git a/js/3p-filters.js b/js/3p-filters.js
index e5ad3d08b..899f07122 100644
--- a/js/3p-filters.js
+++ b/js/3p-filters.js
@@ -33,6 +33,10 @@ var cosmeticSwitch = true;
var externalLists = '';
var cacheWasPurged = false;
var needUpdate = false;
+var hasCachedContent = false;
+
+var reExternalAsset = /^https?:\/\/[a-z0-9]+/;
+var reRepo3rdPartyAsset = /^assets\/thirdparties\/([^\/]+)/;
/******************************************************************************/
@@ -87,7 +91,7 @@ var renderBlacklists = function() {
if ( blacklistHref.indexOf('assets/thirdparties/') !== 0 ) {
return '';
}
- var matches = blacklistHref.match(/^assets\/thirdparties\/([^\/]+)/);
+ var matches = reRepo3rdPartyAsset.exec(blacklistHref);
if ( matches === null || matches.length !== 2 ) {
return '';
}
@@ -136,7 +140,7 @@ var renderBlacklists = function() {
listStatsTemplate,
''
].join('');
- var listKey, list, listEntry, entryDetails;
+ var listKey, list, listEntry, entryDetails, obsolete;
for ( var i = 0; i < listKeys.length; i++ ) {
listKey = listKeys[i];
list = lists[listKey];
@@ -154,23 +158,29 @@ var renderBlacklists = function() {
continue;
}
// Update status
- if ( !list.off && (entryDetails.repoObsolete || entryDetails.cacheObsolete) ) {
- html.push(
- ' ',
- '',
- entryDetails.repoObsolete ? updateButtontext : obsoleteButtontext,
- ''
- );
- needUpdate = true;
+ if ( list.off !== true ) {
+ obsolete = entryDetails.repoObsolete ||
+ entryDetails.cacheObsolete ||
+ entryDetails.cached !== true && reExternalAsset.test(listKey);
+ if ( obsolete ) {
+ html.push(
+ ' ',
+ '',
+ entryDetails.repoObsolete ? updateButtontext : obsoleteButtontext,
+ ''
+ );
+ needUpdate = true;
+ }
}
// In cache
- else if ( entryDetails.cached ) {
+ if ( entryDetails.cached ) {
html.push(
' ',
'',
purgeButtontext,
''
);
+ hasCachedContent = true;
}
}
html.push('
');
@@ -200,6 +210,7 @@ var renderBlacklists = function() {
listDetails = details;
cosmeticSwitch = details.cosmetic;
needUpdate = false;
+ hasCachedContent = false;
var lists = details.available;
var html = [];
@@ -298,6 +309,7 @@ var listsContentChanged = function() {
var updateWidgets = function() {
uDom('#buttonApply').toggleClass('enabled', listsSelectionChanged());
uDom('#buttonUpdate').toggleClass('enabled', listsContentChanged());
+ uDom('#buttonPurgeAll').toggleClass('enabled', hasCachedContent);
};
/******************************************************************************/
@@ -394,6 +406,15 @@ var buttonUpdateHandler = function() {
/******************************************************************************/
+var buttonPurgeAllHandler = function() {
+ var onCompleted = function() {
+ renderBlacklists();
+ };
+ messaging.ask({ what: 'purgeAllCaches' }, onCompleted);
+};
+
+/******************************************************************************/
+
var autoUpdateCheckboxChanged = function() {
messaging.tell({
what: 'userSettings',
@@ -449,6 +470,7 @@ uDom.onLoad(function() {
uDom('#parseCosmeticFilters').on('change', cosmeticSwitchChanged);
uDom('#buttonApply').on('click', buttonApplyHandler);
uDom('#buttonUpdate').on('click', buttonUpdateHandler);
+ uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler);
uDom('#lists').on('change', '.listDetails > input', onListCheckboxChanged);
uDom('#lists').on('click', '.listDetails > a:nth-of-type(1)', onListLinkClicked);
uDom('#lists').on('click', 'span.purge', onPurgeClicked);
diff --git a/js/assets.js b/js/assets.js
index 6baf90bdb..653a14bd7 100644
--- a/js/assets.js
+++ b/js/assets.js
@@ -205,6 +205,18 @@ var cachedAssetsManager = (function() {
getEntries(onEntries);
};
+ exports.removeAll = function(callback) {
+ var onEntries = function() {
+ exports.remove(/^https?:\/\/[a-z0-9]+/);
+ exports.remove(/^assets\/(ublock|thirdparties)\//);
+ exports.remove('assets/checksums.txt');
+ if ( typeof callback === 'function' ) {
+ callback();
+ }
+ };
+ getEntries(onEntries);
+ };
+
return exports;
})();
@@ -956,24 +968,7 @@ exports.purge = function(pattern, before) {
/******************************************************************************/
exports.purgeAll = function(callback) {
- var onMetaDataReady = function(entries) {
- var out = {};
- var entry;
- for ( var path in entries ) {
- if ( entries.hasOwnProperty(path) === false ) {
- continue;
- }
- entry = entries[path];
- if ( !entry.cacheObsolete && !entry.repoObsolete ) {
- continue;
- }
- cachedAssetsManager.remove(path);
- out[path] = true;
- }
- callback(out);
- };
-
- exports.metadata(onMetaDataReady);
+ cachedAssetsManager.removeAll(callback);
};
/******************************************************************************/
diff --git a/js/messaging-handlers.js b/js/messaging-handlers.js
index 7c61d8ff8..89322bdd6 100644
--- a/js/messaging-handlers.js
+++ b/js/messaging-handlers.js
@@ -258,18 +258,13 @@ var getLists = function(callback) {
};
var onMetadataReady = function(entries) {
r.cache = entries;
- if ( r.available ) {
- callback(r);
- }
+ callback(r);
};
var onLists = function(lists) {
r.available = lists;
- if ( r.cache ) {
- callback(r);
- }
+ µb.assets.metadata(onMetadataReady);
};
µb.getAvailableLists(onLists);
- µb.assets.metadata(onMetadataReady);
};
/******************************************************************************/
@@ -282,8 +277,11 @@ var onMessage = function(request, sender, callback) {
case 'getLists':
return getLists(callback);
- case 'readUserUbiquitousBlockRules':
- return µb.assets.get(µb.userFiltersPath, callback);
+ case 'getLists':
+ return getLists(callback);
+
+ case 'purgeAllCaches':
+ return µb.assets.purgeAll(callback);
case 'writeUserUbiquitousBlockRules':
return µb.assets.put(µb.userFiltersPath, request.content, callback);