Skip to content

Commit 693687f

Browse files
committed
Add keyboard support for toggling down blocking profile
Related issue: - uBlockOrigin/uBlock-issues#371 By default, no specific keyboard shortcut is predefined, this will have to be assigned by the user. The command name in English is "Toggle blocking profile". The default behavior is to toggle down according to one of the following scenarios. a) If script execution is disabled through the no-scripting switch, the no-scripting switch will be locally toggled so as to allow script execution. The page will be automatically reloaded. b) If script execution is not blocked but the 3rd-party script and/or frame cells are blocked, local no-op rules will be set so as to no longer block 3rd-party scripts and/or frames. The page will be automatically reloaded. Given this, it may take more than one toggle down command to reach the lowest blocking profile, which is one where JavaScript execution is not blocked and 3rd-party scripts and frames resources block rules, if any, are bypassed with local no-op rules. TODO: At this point, I haven't yet decided whether toggling from the lowest profile should restore the original highest blocking profile.
1 parent d1df2b5 commit 693687f

File tree

6 files changed

+190
-40
lines changed

6 files changed

+190
-40
lines changed

platform/chromium/manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
},
2121
"launch-logger": {
2222
"description": "__MSG_popupTipLog__"
23+
},
24+
"toggle-blocking-profile": {
25+
"description": "__MSG_toggleBlockingProfile__"
2326
}
2427
},
2528
"content_scripts": [

platform/chromium/vapi-background.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ vAPI.tabs.remove = function(tabId) {
607607

608608
/******************************************************************************/
609609

610-
vAPI.tabs.reload = function(tabId, bypassCache) {
610+
vAPI.tabs.reload = function(tabId, bypassCache = false) {
611611
tabId = toChromiumTabId(tabId);
612612
if ( tabId === 0 ) { return; }
613613

src/_locales/en/messages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,10 @@
963963
"message":"Copy to clipboard",
964964
"description":"Label for buttons used to copy something to the clipboard"
965965
},
966+
"toggleBlockingProfile":{
967+
"message":"Toggle blocking profile",
968+
"description":"Label for keyboard shortcut used to toggle blocking profile"
969+
},
966970
"dummy":{
967971
"message":"This entry must be the last one",
968972
"description":"so we dont need to deal with comma for last entry"

src/js/background.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const µBlock = (function() { // jshint ignore:line
4242
autoUpdateAssetFetchPeriod: 120,
4343
autoUpdateDelayAfterLaunch: 180,
4444
autoUpdatePeriod: 7,
45+
blockingProfiles: '11111 11101 00001',
4546
cacheStorageAPI: 'unset',
4647
cacheStorageCompression: true,
4748
cacheControlForFirefox1376932: 'no-cache, no-store, must-revalidate',

src/js/commands.js

Lines changed: 144 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,160 @@
2626
/******************************************************************************/
2727

2828
µBlock.canUseShortcuts = vAPI.commands instanceof Object;
29-
3029
µBlock.canUpdateShortcuts = µBlock.canUseShortcuts &&
3130
typeof vAPI.commands.update === 'function';
3231

3332
/******************************************************************************/
3433

35-
(function() {
36-
if ( µBlock.canUseShortcuts === false ) { return; }
34+
(( ) => {
3735

38-
vAPI.commands.onCommand.addListener(function(command) {
39-
var µb = µBlock;
36+
// *****************************************************************************
37+
// start of local namespace
4038

41-
switch ( command ) {
42-
case 'launch-element-zapper':
43-
case 'launch-element-picker':
44-
vAPI.tabs.get(null, function(tab) {
45-
if ( tab instanceof Object === false ) { return; }
46-
µb.mouseEventRegister.x = µb.mouseEventRegister.y = -1;
47-
µb.elementPickerExec(tab.id, undefined, command === 'launch-element-zapper');
48-
});
39+
if ( µBlock.canUseShortcuts === false ) { return; }
40+
41+
const toggleBlockingProfile = function(tab) {
42+
if (
43+
tab instanceof Object === false ||
44+
tab.id <= 0
45+
) {
46+
return;
47+
}
48+
49+
const µb = µBlock;
50+
const normalURL = µb.normalizePageURL(tab.id, tab.url);
51+
52+
if ( µb.getNetFilteringSwitch(normalURL) === false ) { return; }
53+
54+
const hn = µb.URI.hostnameFromURI(normalURL);
55+
56+
// Construct current blocking profile
57+
const ssw = µb.sessionSwitches;
58+
const sfw = µb.sessionFirewall;
59+
let currentProfile = 0;
60+
61+
if ( ssw.evaluateZ('no-scripting', hn) ) {
62+
currentProfile |= 0b00000010;
63+
}
64+
if ( µb.userSettings.advancedUserEnabled ) {
65+
if ( sfw.evaluateCellZY(hn, '*', '3p') === 1 ) {
66+
currentProfile |= 0b00000100;
67+
}
68+
if ( sfw.evaluateCellZY(hn, '*', '3p-script') === 1 ) {
69+
currentProfile |= 0b00001000;
70+
}
71+
if ( sfw.evaluateCellZY(hn, '*', '3p-frame') === 1 ) {
72+
currentProfile |= 0b00010000;
73+
}
74+
}
75+
76+
const profiles = [];
77+
for ( const s of µb.hiddenSettings.blockingProfiles.split(/\s+/) ) {
78+
const v = parseInt(s, 2);
79+
if ( isNaN(v) ) { continue; }
80+
profiles.push(v);
81+
}
82+
let newProfile;
83+
for ( const profile of profiles ) {
84+
if ( (currentProfile & profile & 0b11111110) !== currentProfile ) {
85+
newProfile = profile;
4986
break;
50-
case 'launch-logger':
51-
vAPI.tabs.get(null, function(tab) {
52-
let hash = tab.url.startsWith(vAPI.getURL('')) ?
53-
'' :
54-
'#_+' + tab.id;
55-
µb.openNewTab({
56-
url: 'logger-ui.html' + hash,
57-
select: true,
58-
index: -1
59-
});
87+
}
88+
}
89+
90+
// TODO: Reset to original blocking profile?
91+
if ( newProfile === undefined ) { return; }
92+
93+
if (
94+
(currentProfile & 0b00000010) !== 0 &&
95+
(newProfile & 0b00000010) === 0
96+
) {
97+
µb.toggleHostnameSwitch({
98+
name: 'no-scripting',
99+
hostname: hn,
100+
state: false,
101+
});
102+
}
103+
if ( µb.userSettings.advancedUserEnabled ) {
104+
if (
105+
(currentProfile & 0b00000100) !== 0 &&
106+
(newProfile & 0b00000100) === 0
107+
) {
108+
µb.toggleFirewallRule({
109+
srcHostname: hn,
110+
desHostname: '*',
111+
requestType: '3p',
112+
action: 3,
113+
});
114+
}
115+
if (
116+
(currentProfile & 0b00001000) !== 0 &&
117+
(newProfile & 0b00001000) === 0
118+
) {
119+
µb.toggleFirewallRule({
120+
srcHostname: hn,
121+
desHostname: '*',
122+
requestType: '3p-script',
123+
action: 3,
124+
});
125+
}
126+
if (
127+
(currentProfile & 0b00010000) !== 0 &&
128+
(newProfile & 0b00010000) === 0
129+
) {
130+
µb.toggleFirewallRule({
131+
srcHostname: hn,
132+
desHostname: '*',
133+
requestType: '3p-frame',
134+
action: 3,
60135
});
61-
break;
62-
default:
63-
break;
64136
}
65-
});
137+
}
138+
139+
if ( newProfile & 0b00000001 ) {
140+
vAPI.tabs.reload(tab.id);
141+
}
142+
};
143+
144+
vAPI.commands.onCommand.addListener(command => {
145+
const µb = µBlock;
146+
147+
switch ( command ) {
148+
case 'launch-element-picker':
149+
case 'launch-element-zapper':
150+
vAPI.tabs.get(null, tab => {
151+
if ( tab instanceof Object === false ) { return; }
152+
µb.mouseEventRegister.x = µb.mouseEventRegister.y = -1;
153+
µb.elementPickerExec(
154+
tab.id,
155+
undefined,
156+
command === 'launch-element-zapper'
157+
);
158+
});
159+
break;
160+
case 'launch-logger':
161+
vAPI.tabs.get(null, tab => {
162+
const hash = tab.url.startsWith(vAPI.getURL(''))
163+
? ''
164+
: `#_+${tab.id}`;
165+
µb.openNewTab({
166+
url: `logger-ui.html${hash}`,
167+
select: true,
168+
index: -1
169+
});
170+
});
171+
break;
172+
case 'toggle-blocking-profile':
173+
vAPI.tabs.get(null, toggleBlockingProfile);
174+
break;
175+
default:
176+
break;
177+
}
178+
});
179+
180+
// end of local namespace
181+
// *****************************************************************************
182+
66183
})();
67184

68185
/******************************************************************************/

src/js/ublock.js

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
/******************************************************************************/
2525
/******************************************************************************/
2626

27+
{
28+
2729
// *****************************************************************************
2830
// start of local namespace
2931

30-
{
31-
3232
// https://github.com/chrisaljoudi/uBlock/issues/405
3333
// Be more flexible with whitelist syntax
3434

@@ -451,20 +451,39 @@ const matchBucket = function(url, hostname, bucket, start) {
451451
// (but not really) redundant rules led to this issue.
452452

453453
µBlock.toggleFirewallRule = function(details) {
454-
let requestType = details.requestType;
455-
456-
if ( details.action !== 0 ) {
457-
this.sessionFirewall.setCell(details.srcHostname, details.desHostname, requestType, details.action);
454+
let { srcHostname, desHostname, requestType, action } = details;
455+
456+
if ( action !== 0 ) {
457+
this.sessionFirewall.setCell(
458+
srcHostname,
459+
desHostname,
460+
requestType,
461+
action
462+
);
458463
} else {
459-
this.sessionFirewall.unsetCell(details.srcHostname, details.desHostname, requestType);
464+
this.sessionFirewall.unsetCell(
465+
srcHostname,
466+
desHostname,
467+
requestType
468+
);
460469
}
461470

462471
// https://github.com/chrisaljoudi/uBlock/issues/731#issuecomment-73937469
463472
if ( details.persist ) {
464-
if ( details.action !== 0 ) {
465-
this.permanentFirewall.setCell(details.srcHostname, details.desHostname, requestType, details.action);
473+
if ( action !== 0 ) {
474+
this.permanentFirewall.setCell(
475+
srcHostname,
476+
desHostname,
477+
requestType,
478+
action
479+
);
466480
} else {
467-
this.permanentFirewall.unsetCell(details.srcHostname, details.desHostname, requestType, details.action);
481+
this.permanentFirewall.unsetCell(
482+
srcHostname,
483+
desHostname,
484+
requestType,
485+
action
486+
);
468487
}
469488
this.savePermanentFirewallRules();
470489
}
@@ -473,10 +492,14 @@ const matchBucket = function(url, hostname, bucket, start) {
473492
// Flush all cached `net` cosmetic filters if we are dealing with a
474493
// collapsible type: any of the cached entries could be a resource on the
475494
// target page.
476-
let srcHostname = details.srcHostname;
477495
if (
478496
(srcHostname !== '*') &&
479-
(requestType === '*' || requestType === 'image' || requestType === '3p' || requestType === '3p-frame')
497+
(
498+
requestType === '*' ||
499+
requestType === 'image' ||
500+
requestType === '3p' ||
501+
requestType === '3p-frame'
502+
)
480503
) {
481504
srcHostname = '*';
482505
}
@@ -635,3 +658,5 @@ const matchBucket = function(url, hostname, bucket, start) {
635658
report: report
636659
};
637660
})();
661+
662+
/******************************************************************************/

0 commit comments

Comments
 (0)