aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/_locales/en/messages.json4
-rw-r--r--src/about.html10
-rw-r--r--src/css/common.css4
-rw-r--r--src/css/popup.css45
-rw-r--r--src/dashboard.html2
-rw-r--r--src/js/about.js93
-rw-r--r--src/js/background.js1
-rw-r--r--src/js/dashboard.js2
-rw-r--r--src/js/messaging.js17
-rw-r--r--src/js/pagestore.js10
-rw-r--r--src/js/popup.js24
-rw-r--r--src/js/settings.js113
-rw-r--r--src/js/storage.js5
-rw-r--r--src/settings.html13
14 files changed, 167 insertions, 176 deletions
diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json
index 7039432..bdf6813 100644
--- a/src/_locales/en/messages.json
+++ b/src/_locales/en/messages.json
@@ -215,6 +215,10 @@
"message":"Make use of context menu where appropriate",
"description":"English: Make use of context menu where appropriate"
},
+ "settingsAdvancedUserPrompt":{
+ "message":"I am an advanced user (<a href='https:\/\/github.com\/gorhill\/uBlock\/wiki\/Advanced-user-features'>About<\/a>)",
+ "description":"English: "
+ },
"settingsExperimentalPrompt":{
"message":"Enable experimental features (<a href='https:\/\/github.com\/gorhill\/uBlock\/wiki\/Experimental-features'>About<\/a>)",
"description":"English: Enable experimental features"
diff --git a/src/about.html b/src/about.html
index 9413ab9..77a8361 100644
--- a/src/about.html
+++ b/src/about.html
@@ -22,16 +22,6 @@
</ul>
</ul>
-<div style="margin:3em 0;border-top:1px solid #ccc;"></div>
-
-<div style="margin:1em 0 0 0;">
-<p><button type="button" id="export" data-i18n="aboutBackupDataButton"></button>
- <button type="button" id="import" data-i18n="aboutRestoreDataButton"></button>
- <input id="restoreFilePicker" type="file" accept="text/plain" class="hiddenFileInput">
-<p>
-<p><button type="button" id="reset" data-i18n="aboutResetDataButton"></button>
-</div>
-
<script src="js/vapi-common.js"></script>
<script src="js/vapi-client.js"></script>
<script src="js/udom.js"></script>
diff --git a/src/css/common.css b/src/css/common.css
index 0fd5e80..93fcd65 100644
--- a/src/css/common.css
+++ b/src/css/common.css
@@ -18,14 +18,14 @@
cursor: pointer;
position: relative;
}
-[data-tip]:hover:after {
+body:not(.advancedUser) [data-tip]:hover:after {
background-color: #ffffee;
border: 1px solid gray;
border-radius: 3px;
box-shadow: 1px 1px 3px gray;
color: black;
content: attr(data-tip);
- font: 11px sans-serif;
+ font: 12px sans-serif;
left: 0;
line-height: 130%;
min-width: 55%;
diff --git a/src/css/popup.css b/src/css/popup.css
index cb0ac5e..5d67f49 100644
--- a/src/css/popup.css
+++ b/src/css/popup.css
@@ -62,6 +62,7 @@ body[dir="rtl"] #panes > div:nth-of-type(2) {
}
#panes > div:nth-of-type(1) {
+ min-width: 150px;
padding: 4px 5px 0 5px;
}
p {
@@ -115,43 +116,17 @@ p {
color: #444;
}
-#dfToggler::before {
+body.advancedUser #dfToggler::before {
color: gray;
content: '+\202F';
cursor: pointer;
font-size: 14px;
line-height: 14px;
}
-#panes.dfEnabled #dfToggler::before {
+body.advancedUser #panes.dfEnabled #dfToggler::before {
content: '\2212\202F';
}
-.dynamicFiltering div > .tip {
- background-color: #fffff4;
- border: 1px solid #888;
- border-radius: 5px;
- bottom: 20%;
- box-shadow: 1px 1px 2px 0 rgba(0,0,0,0.8);
- display: none;
- font-size: small;
- left: 8%;
- padding: 0.25em;
- position: fixed;
- right: 8%;
- text-align: center;
- }
-.dynamicFiltering div:not(.blocked):hover > .tip:nth-of-type(1) {
- display: block;
- }
-.dynamicFiltering div.blocked:hover > .tip:nth-of-type(2) {
- display: block;
- }
-.dynamicFiltering div > .tip code {
- background-color: #f8f8f8;
- font: normal monospace;
- padding: 1px 0;
- }
-
#dynamicFilteringContainer {
border: 0;
font-size: 12px;
@@ -269,17 +244,3 @@ p {
#dynamicFilteringContainer span.bRule #actionSelector > span:nth-of-type(3) {
visibility: hidden;
}
-#hotspotTip {
- background-color: #ffe;
- border: 1px dotted #ddb;
- border-radius: 5px;
- height: 50vh;
- opacity: 1;
- padding: 4px;
- position: fixed;
- right: 10px;
- text-align: center;
- top: 25vh;
- width: 20vw;
- z-index: 100;
- } \ No newline at end of file
diff --git a/src/dashboard.html b/src/dashboard.html
index 4c36f62..ac7e5a6 100644
--- a/src/dashboard.html
+++ b/src/dashboard.html
@@ -11,11 +11,11 @@
<div id="dashboard-nav">
<div id="dashboard-nav-widgets">
<span data-i18n="extName"></span>
+ <a class="tabButton" href="#settings.html" data-i18n="settingsPageName"></a>
<a class="tabButton" href="#3p-filters.html" data-i18n="3pPageName"></a>
<a class="tabButton" href="#1p-filters.html" data-i18n="1pPageName"></a>
<a class="tabButton" href="#dyna-rules.html" data-i18n="rulesPageName"></a>
<a class="tabButton" href="#whitelist.html" data-i18n="whitelistPageName"></a>
- <a class="tabButton" href="#settings.html" data-i18n="settingsPageName"></a>
<a class="tabButton" href="#about.html" data-i18n="aboutPageName"></a>
</div>
</div>
diff --git a/src/js/about.js b/src/js/about.js
index 2e2c5c7..66155c6 100644
--- a/src/js/about.js
+++ b/src/js/about.js
@@ -33,101 +33,8 @@ var messager = vAPI.messaging.channel('about.js');
/******************************************************************************/
-var exportToFile = function() {
- var onUserDataReady = function(userData) {
- if (!userData) {
- return;
- }
- var now = new Date();
- var filename = vAPI.i18n('aboutBackupFilename')
- .replace('{{datetime}}', now.toLocaleString())
- .replace(/ +/g, '_');
- vAPI.download({
- 'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(userData, null, ' ')),
- 'filename': filename
- });
- };
-
- messager.send({ what: 'getUserData' }, onUserDataReady);
-};
-
-/******************************************************************************/
-
-var handleImportFilePicker = function() {
- var fileReaderOnLoadHandler = function() {
- var userData;
- try {
- userData = JSON.parse(this.result);
- if ( typeof userData !== 'object' ) {
- throw 'Invalid';
- }
- if ( typeof userData.userSettings !== 'object' ) {
- throw 'Invalid';
- }
- if ( typeof userData.netWhitelist !== 'string' ) {
- throw 'Invalid';
- }
- if ( typeof userData.filterLists !== 'object' ) {
- throw 'Invalid';
- }
- }
- catch (e) {
- userData = undefined;
- }
- if ( userData === undefined ) {
- window.alert(vAPI.i18n('aboutRestoreDataError'));
- return;
- }
- var time = new Date(userData.timeStamp);
- var msg = vAPI.i18n('aboutRestoreDataConfirm')
- .replace('{{time}}', time.toLocaleString());
- var proceed = window.confirm(msg);
- if ( proceed ) {
- messager.send({ what: 'restoreUserData', userData: userData });
- }
- };
-
- var file = this.files[0];
- if ( file === undefined || file.name === '' ) {
- return;
- }
- if ( file.type.indexOf('text') !== 0 ) {
- return;
- }
- var fr = new FileReader();
- fr.onload = fileReaderOnLoadHandler;
- fr.readAsText(file);
-};
-
-/******************************************************************************/
-
-var startImportFilePicker = function() {
- var input = document.getElementById('restoreFilePicker');
- // Reset to empty string, this will ensure an change event is properly
- // triggered if the user pick a file, even if it is the same as the last
- // one picked.
- input.value = '';
- input.click();
-};
-
-/******************************************************************************/
-
-var resetUserData = function() {
- var msg = vAPI.i18n('aboutResetDataConfirm');
- var proceed = window.confirm(msg);
- if ( proceed ) {
- messager.send({ what: 'resetUserData' });
- }
-};
-
-/******************************************************************************/
-
var onAppDataReady = function(appData) {
uDom('#aboutNameVer').html(appData.name + ' v' + appData.version);
- uDom('#export').on('click', exportToFile);
- uDom('#import').on('click', startImportFilePicker);
- uDom('#reset').on('click', resetUserData);
- uDom('#restoreFilePicker').on('change', handleImportFilePicker);
};
messager.send({ what: 'getAppData' }, onAppDataReady);
diff --git a/src/js/background.js b/src/js/background.js
index 4a98ab1..4306d65 100644
--- a/src/js/background.js
+++ b/src/js/background.js
@@ -52,6 +52,7 @@ var defaultExternalLists = [
return {
userSettings: {
+ advancedUserEnabled: false,
autoUpdate: true,
collapseBlocked: true,
contextMenuEnabled: true,
diff --git a/src/js/dashboard.js b/src/js/dashboard.js
index 6779f27..ba916e2 100644
--- a/src/js/dashboard.js
+++ b/src/js/dashboard.js
@@ -59,7 +59,7 @@ uDom.onLoad(function() {
}
}
if ( !tab ) {
- tab = '3p-filters';
+ tab = 'settings';
}
loadDashboardPanel(tab + '.html', q);
uDom('.tabButton').on('click', onTabClickHandler);
diff --git a/src/js/messaging.js b/src/js/messaging.js
index aa95a7e..90ec132 100644
--- a/src/js/messaging.js
+++ b/src/js/messaging.js
@@ -171,17 +171,18 @@ var getDynamicFilterRules = function(srcHostname, desHostnames) {
var getStats = function(tabId) {
var r = {
+ advancedUserEnabled: µb.userSettings.advancedUserEnabled,
appName: vAPI.app.name,
appVersion: vAPI.app.version,
- globalBlockedRequestCount: µb.localSettings.blockedRequestCount,
+ cosmeticFilteringSwitch: false,
+ dfEnabled: µb.userSettings.dynamicFilteringEnabled,
globalAllowedRequestCount: µb.localSettings.allowedRequestCount,
- tabId: tabId,
+ globalBlockedRequestCount: µb.localSettings.blockedRequestCount,
+ netFilteringSwitch: false,
pageURL: '',
- pageBlockedRequestCount: 0,
pageAllowedRequestCount: 0,
- netFilteringSwitch: false,
- cosmeticFilteringSwitch: false,
- dfEnabled: µb.userSettings.dynamicFilteringEnabled
+ pageBlockedRequestCount: 0,
+ tabId: tabId
};
var pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore ) {
@@ -811,7 +812,7 @@ vAPI.messaging.listen('stats.js', onMessage);
/******************************************************************************/
/******************************************************************************/
-// about.js
+// settings.js
(function() {
@@ -902,7 +903,7 @@ var onMessage = function(request, sender, callback) {
callback(response);
};
-vAPI.messaging.listen('about.js', onMessage);
+vAPI.messaging.listen('settings.js', onMessage);
/******************************************************************************/
diff --git a/src/js/pagestore.js b/src/js/pagestore.js
index 24cb3ec..f5f52bf 100644
--- a/src/js/pagestore.js
+++ b/src/js/pagestore.js
@@ -615,10 +615,12 @@ PageStore.prototype.filterRequest = function(context) {
// - Evaluating dynamic filtering is much faster than static filtering
// We evaluate dynamic filtering first, and hopefully we can skip
// evaluation of static filtering.
- var df = µb.dynamicNetFilteringEngine.clearRegisters();
- df.evaluateCellZY(context.rootHostname, context.requestHostname, context.requestType);
- if ( df.mustBlockOrAllow() ) {
- result = df.toFilterString();
+ if ( µb.userSettings.advancedUserEnabled ) {
+ var df = µb.dynamicNetFilteringEngine.clearRegisters();
+ df.evaluateCellZY(context.rootHostname, context.requestHostname, context.requestType);
+ if ( df.mustBlockOrAllow() ) {
+ result = df.toFilterString();
+ }
}
// Static filtering never override dynamic filtering
diff --git a/src/js/popup.js b/src/js/popup.js
index 0d706bb..48775f4 100644
--- a/src/js/popup.js
+++ b/src/js/popup.js
@@ -117,7 +117,7 @@ var reRulekeyCompareNoise = /[^a-z0-9.]/g;
var addDynamicFilterRow = function(des) {
var row = uDom('#templates > div:nth-of-type(1)').clone();
row.descendants('[data-des]').attr('data-des', des);
- row.descendants('div > span:nth-of-type(1)').text(des);
+ row.descendants('span:nth-of-type(1)').text(des);
var hnDetails = popupData.hostnameDict[des] || {};
var isDomain = des === hnDetails.domain;
@@ -245,16 +245,17 @@ var renderPopup = function() {
var isHTTP = /^https?:\/\/[0-9a-z]/.test(popupData.pageURL);
+ // Condition for dynamic filtering toggler:
+ // - Advanced user
+ uDom('body').toggleClass('advancedUser', popupData.advancedUserEnabled);
+
// Conditions for request log:
- // - `http` or `https` scheme
+ // - `http` or `https` scheme
uDom('#gotoLog').toggleClass('enabled', isHTTP);
// Conditions for element picker:
- // - `http` or `https` scheme
- uDom('#gotoPick').toggleClass(
- 'enabled',
- isHTTP
- );
+ // - `http` or `https` scheme
+ uDom('#gotoPick').toggleClass('enabled', isHTTP);
var or = vAPI.i18n('popupOr');
var blocked = popupData.pageBlockedRequestCount;
@@ -289,15 +290,15 @@ var renderPopup = function() {
'%</span>'
);
}
+ uDom('#total-blocked').html(html.join(''));
// Build dynamic filtering pane only if in use
- if ( popupData.dfEnabled ) {
+ if ( popupData.dfEnabled && popupData.advancedUserEnabled ) {
syncAllDynamicFilters();
}
- uDom('#total-blocked').html(html.join(''));
uDom('#switch .fa').toggleClass('off', popupData.pageURL === '' || !popupData.netFilteringSwitch);
- uDom('#panes').toggleClass('dfEnabled', popupData.dfEnabled);
+ uDom('#panes').toggleClass('dfEnabled', popupData.dfEnabled && popupData.advancedUserEnabled);
};
/******************************************************************************/
@@ -373,6 +374,9 @@ var gotoLink = function(ev) {
/******************************************************************************/
var toggleDynamicFiltering = function(ev) {
+ if ( uDom('body').hasClass('advancedUser') === false ) {
+ return;
+ }
var el = uDom('#panes');
popupData.dfEnabled = !popupData.dfEnabled;
messager.send({
diff --git a/src/js/settings.js b/src/js/settings.js
index acd1625..cf9981b 100644
--- a/src/js/settings.js
+++ b/src/js/settings.js
@@ -20,11 +20,12 @@
*/
/* global vAPI, uDom */
-'use strict';
/******************************************************************************/
-uDom.onLoad(function() {
+(function() {
+
+'use strict';
/******************************************************************************/
@@ -32,6 +33,95 @@ var messager = vAPI.messaging.channel('settings.js');
/******************************************************************************/
+var exportToFile = function() {
+ var onUserDataReady = function(userData) {
+ if (!userData) {
+ return;
+ }
+ var now = new Date();
+ var filename = vAPI.i18n('aboutBackupFilename')
+ .replace('{{datetime}}', now.toLocaleString())
+ .replace(/ +/g, '_');
+ vAPI.download({
+ 'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(userData, null, ' ')),
+ 'filename': filename
+ });
+ };
+
+ messager.send({ what: 'getUserData' }, onUserDataReady);
+};
+
+/******************************************************************************/
+
+var handleImportFilePicker = function() {
+ var fileReaderOnLoadHandler = function() {
+ var userData;
+ try {
+ userData = JSON.parse(this.result);
+ if ( typeof userData !== 'object' ) {
+ throw 'Invalid';
+ }
+ if ( typeof userData.userSettings !== 'object' ) {
+ throw 'Invalid';
+ }
+ if ( typeof userData.netWhitelist !== 'string' ) {
+ throw 'Invalid';
+ }
+ if ( typeof userData.filterLists !== 'object' ) {
+ throw 'Invalid';
+ }
+ }
+ catch (e) {
+ userData = undefined;
+ }
+ if ( userData === undefined ) {
+ window.alert(vAPI.i18n('aboutRestoreDataError'));
+ return;
+ }
+ var time = new Date(userData.timeStamp);
+ var msg = vAPI.i18n('aboutRestoreDataConfirm')
+ .replace('{{time}}', time.toLocaleString());
+ var proceed = window.confirm(msg);
+ if ( proceed ) {
+ messager.send({ what: 'restoreUserData', userData: userData });
+ }
+ };
+
+ var file = this.files[0];
+ if ( file === undefined || file.name === '' ) {
+ return;
+ }
+ if ( file.type.indexOf('text') !== 0 ) {
+ return;
+ }
+ var fr = new FileReader();
+ fr.onload = fileReaderOnLoadHandler;
+ fr.readAsText(file);
+};
+
+/******************************************************************************/
+
+var startImportFilePicker = function() {
+ var input = document.getElementById('restoreFilePicker');
+ // Reset to empty string, this will ensure an change event is properly
+ // triggered if the user pick a file, even if it is the same as the last
+ // one picked.
+ input.value = '';
+ input.click();
+};
+
+/******************************************************************************/
+
+var resetUserData = function() {
+ var msg = vAPI.i18n('aboutResetDataConfirm');
+ var proceed = window.confirm(msg);
+ if ( proceed ) {
+ messager.send({ what: 'resetUserData' });
+ }
+};
+
+/******************************************************************************/
+
var changeUserSettings = function(name, value) {
messager.send({
what: 'userSettings',
@@ -63,15 +153,30 @@ var onUserSettingsReceived = function(details) {
changeUserSettings('contextMenuEnabled', this.checked);
});
+ uDom('#advanced-user-enabled')
+ .prop('checked', details.advancedUserEnabled === true)
+ .on('change', function(){
+ changeUserSettings('advancedUserEnabled', this.checked);
+ });
+
uDom('#experimental-enabled')
.prop('checked', details.experimentalEnabled === true)
.on('change', function(){
changeUserSettings('experimentalEnabled', this.checked);
});
-};
-messager.send({ what: 'userSettings' }, onUserSettingsReceived);
+ uDom('#export').on('click', exportToFile);
+ uDom('#import').on('click', startImportFilePicker);
+ uDom('#reset').on('click', resetUserData);
+ uDom('#restoreFilePicker').on('change', handleImportFilePicker);
+};
/******************************************************************************/
+uDom.onLoad(function() {
+ messager.send({ what: 'userSettings' }, onUserSettingsReceived);
});
+
+/******************************************************************************/
+
+})();
diff --git a/src/js/storage.js b/src/js/storage.js
index 044ec86..b98a67c 100644
--- a/src/js/storage.js
+++ b/src/js/storage.js
@@ -670,11 +670,14 @@
µb.dynamicNetFilteringEngine.fromObsoleteSelfie(settings.dynamicFilteringSelfie);
µb.userSettings.dynamicFilteringString = µb.dynamicNetFilteringEngine.toString();
µb.XAL.keyvalSetOne('dynamicFilteringString', µb.userSettings.dynamicFilteringString);
+
+ // Auto-enable advanced user if there were dynamic rules
+ µb.userSettings.advancedUserEnabled = true;
+ µb.XAL.keyvalSetOne('advancedUserEnabled', true);
}
delete µb.userSettings.dynamicFilteringSelfie;
µb.XAL.keyvalRemoveOne('dynamicFilteringSelfie');
}
- µb.dynamicNetFilteringEngine.fromString(µb.userSettings.dynamicFilteringString);
};
this.loadUserSettings(onUserSettingsReady);
diff --git a/src/settings.html b/src/settings.html
index 242370e..fa5fb1e 100644
--- a/src/settings.html
+++ b/src/settings.html
@@ -8,6 +8,7 @@
<style>
ul {
list-style-type: none;
+ padding-left: 1em;
}
#experimental-enabled {
margin-top: 1em;
@@ -21,9 +22,21 @@ ul {
<li><input id="collapse-blocked" type="checkbox"><label data-i18n="settingsCollapseBlockedPrompt" for="collapse-blocked"></label>
<li><input id="icon-badge" type="checkbox"><label data-i18n="settingsIconBadgePrompt" for="icon-badge"></label>
<li><input id="context-menu-enabled" type="checkbox"><label data-i18n="settingsContextMenuPrompt" for="context-menu-enabled"></label>
+ <li><input id="advanced-user-enabled" type="checkbox"><label data-i18n="settingsAdvancedUserPrompt" for="advanced-user-enabled"></label>
+
<li><input id="experimental-enabled" type="checkbox"><label data-i18n="settingsExperimentalPrompt" for="experimental-enabled"></label>
</ul>
+<div style="margin:3em 0;border-top:1px solid #ccc;"></div>
+
+<div style="margin:1em 0 0 1em;">
+ <p><button type="button" id="export" data-i18n="aboutBackupDataButton"></button>&ensp;
+ <button type="button" id="import" data-i18n="aboutRestoreDataButton"></button>
+ <input id="restoreFilePicker" type="file" accept="text/plain" class="hiddenFileInput">
+ <p>
+ <p><button type="button" id="reset" data-i18n="aboutResetDataButton"></button>
+</div>
+
<script src="js/vapi-common.js"></script>
<script src="js/vapi-client.js"></script>
<script src="js/udom.js"></script>