diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json index 1edcab985..e5d0b98d1 100644 --- a/platform/chromium/manifest.json +++ b/platform/chromium/manifest.json @@ -20,6 +20,9 @@ }, "launch-logger": { "description": "__MSG_popupTipLog__" + }, + "toggle-blocking-profile": { + "description": "__MSG_toggleBlockingProfile__" } }, "content_scripts": [ diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 301577a48..66c2249bf 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -607,7 +607,7 @@ vAPI.tabs.remove = function(tabId) { /******************************************************************************/ -vAPI.tabs.reload = function(tabId, bypassCache) { +vAPI.tabs.reload = function(tabId, bypassCache = false) { tabId = toChromiumTabId(tabId); if ( tabId === 0 ) { return; } diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index b65f6320a..6afcd9702 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -963,6 +963,10 @@ "message":"Copy to clipboard", "description":"Label for buttons used to copy something to the clipboard" }, + "toggleBlockingProfile":{ + "message":"Toggle blocking profile", + "description":"Label for keyboard shortcut used to toggle blocking profile" + }, "dummy":{ "message":"This entry must be the last one", "description":"so we dont need to deal with comma for last entry" diff --git a/src/js/background.js b/src/js/background.js index 036c9b309..ff756ea43 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -42,6 +42,7 @@ const µBlock = (function() { // jshint ignore:line autoUpdateAssetFetchPeriod: 120, autoUpdateDelayAfterLaunch: 180, autoUpdatePeriod: 7, + blockingProfiles: '11111 11101 00001', cacheStorageAPI: 'unset', cacheStorageCompression: true, cacheControlForFirefox1376932: 'no-cache, no-store, must-revalidate', diff --git a/src/js/commands.js b/src/js/commands.js index a8036cd4d..3b5abd05b 100644 --- a/src/js/commands.js +++ b/src/js/commands.js @@ -26,43 +26,160 @@ /******************************************************************************/ µBlock.canUseShortcuts = vAPI.commands instanceof Object; - µBlock.canUpdateShortcuts = µBlock.canUseShortcuts && typeof vAPI.commands.update === 'function'; /******************************************************************************/ -(function() { - if ( µBlock.canUseShortcuts === false ) { return; } +(( ) => { - vAPI.commands.onCommand.addListener(function(command) { - var µb = µBlock; +// ***************************************************************************** +// start of local namespace - switch ( command ) { - case 'launch-element-zapper': - case 'launch-element-picker': - vAPI.tabs.get(null, function(tab) { - if ( tab instanceof Object === false ) { return; } - µb.mouseEventRegister.x = µb.mouseEventRegister.y = -1; - µb.elementPickerExec(tab.id, undefined, command === 'launch-element-zapper'); - }); - break; - case 'launch-logger': - vAPI.tabs.get(null, function(tab) { - let hash = tab.url.startsWith(vAPI.getURL('')) ? - '' : - '#_+' + tab.id; - µb.openNewTab({ - url: 'logger-ui.html' + hash, - select: true, - index: -1 - }); - }); - break; - default: +if ( µBlock.canUseShortcuts === false ) { return; } + +const toggleBlockingProfile = function(tab) { + if ( + tab instanceof Object === false || + tab.id <= 0 + ) { + return; + } + + const µb = µBlock; + const normalURL = µb.normalizePageURL(tab.id, tab.url); + + if ( µb.getNetFilteringSwitch(normalURL) === false ) { return; } + + const hn = µb.URI.hostnameFromURI(normalURL); + + // Construct current blocking profile + const ssw = µb.sessionSwitches; + const sfw = µb.sessionFirewall; + let currentProfile = 0; + + if ( ssw.evaluateZ('no-scripting', hn) ) { + currentProfile |= 0b00000010; + } + if ( µb.userSettings.advancedUserEnabled ) { + if ( sfw.evaluateCellZY(hn, '*', '3p') === 1 ) { + currentProfile |= 0b00000100; + } + if ( sfw.evaluateCellZY(hn, '*', '3p-script') === 1 ) { + currentProfile |= 0b00001000; + } + if ( sfw.evaluateCellZY(hn, '*', '3p-frame') === 1 ) { + currentProfile |= 0b00010000; + } + } + + const profiles = []; + for ( const s of µb.hiddenSettings.blockingProfiles.split(/\s+/) ) { + const v = parseInt(s, 2); + if ( isNaN(v) ) { continue; } + profiles.push(v); + } + let newProfile; + for ( const profile of profiles ) { + if ( (currentProfile & profile & 0b11111110) !== currentProfile ) { + newProfile = profile; break; } - }); + } + + // TODO: Reset to original blocking profile? + if ( newProfile === undefined ) { return; } + + if ( + (currentProfile & 0b00000010) !== 0 && + (newProfile & 0b00000010) === 0 + ) { + µb.toggleHostnameSwitch({ + name: 'no-scripting', + hostname: hn, + state: false, + }); + } + if ( µb.userSettings.advancedUserEnabled ) { + if ( + (currentProfile & 0b00000100) !== 0 && + (newProfile & 0b00000100) === 0 + ) { + µb.toggleFirewallRule({ + srcHostname: hn, + desHostname: '*', + requestType: '3p', + action: 3, + }); + } + if ( + (currentProfile & 0b00001000) !== 0 && + (newProfile & 0b00001000) === 0 + ) { + µb.toggleFirewallRule({ + srcHostname: hn, + desHostname: '*', + requestType: '3p-script', + action: 3, + }); + } + if ( + (currentProfile & 0b00010000) !== 0 && + (newProfile & 0b00010000) === 0 + ) { + µb.toggleFirewallRule({ + srcHostname: hn, + desHostname: '*', + requestType: '3p-frame', + action: 3, + }); + } + } + + if ( newProfile & 0b00000001 ) { + vAPI.tabs.reload(tab.id); + } +}; + +vAPI.commands.onCommand.addListener(command => { + const µb = µBlock; + + switch ( command ) { + case 'launch-element-picker': + case 'launch-element-zapper': + vAPI.tabs.get(null, tab => { + if ( tab instanceof Object === false ) { return; } + µb.mouseEventRegister.x = µb.mouseEventRegister.y = -1; + µb.elementPickerExec( + tab.id, + undefined, + command === 'launch-element-zapper' + ); + }); + break; + case 'launch-logger': + vAPI.tabs.get(null, tab => { + const hash = tab.url.startsWith(vAPI.getURL('')) + ? '' + : `#_+${tab.id}`; + µb.openNewTab({ + url: `logger-ui.html${hash}`, + select: true, + index: -1 + }); + }); + break; + case 'toggle-blocking-profile': + vAPI.tabs.get(null, toggleBlockingProfile); + break; + default: + break; + } +}); + +// end of local namespace +// ***************************************************************************** + })(); /******************************************************************************/ diff --git a/src/js/ublock.js b/src/js/ublock.js index 68130cd8b..d151f12ef 100644 --- a/src/js/ublock.js +++ b/src/js/ublock.js @@ -24,11 +24,11 @@ /******************************************************************************/ /******************************************************************************/ +{ + // ***************************************************************************** // start of local namespace -{ - // https://github.com/chrisaljoudi/uBlock/issues/405 // Be more flexible with whitelist syntax @@ -451,20 +451,39 @@ const matchBucket = function(url, hostname, bucket, start) { // (but not really) redundant rules led to this issue. µBlock.toggleFirewallRule = function(details) { - let requestType = details.requestType; + let { srcHostname, desHostname, requestType, action } = details; - if ( details.action !== 0 ) { - this.sessionFirewall.setCell(details.srcHostname, details.desHostname, requestType, details.action); + if ( action !== 0 ) { + this.sessionFirewall.setCell( + srcHostname, + desHostname, + requestType, + action + ); } else { - this.sessionFirewall.unsetCell(details.srcHostname, details.desHostname, requestType); + this.sessionFirewall.unsetCell( + srcHostname, + desHostname, + requestType + ); } // https://github.com/chrisaljoudi/uBlock/issues/731#issuecomment-73937469 if ( details.persist ) { - if ( details.action !== 0 ) { - this.permanentFirewall.setCell(details.srcHostname, details.desHostname, requestType, details.action); + if ( action !== 0 ) { + this.permanentFirewall.setCell( + srcHostname, + desHostname, + requestType, + action + ); } else { - this.permanentFirewall.unsetCell(details.srcHostname, details.desHostname, requestType, details.action); + this.permanentFirewall.unsetCell( + srcHostname, + desHostname, + requestType, + action + ); } this.savePermanentFirewallRules(); } @@ -473,10 +492,14 @@ const matchBucket = function(url, hostname, bucket, start) { // Flush all cached `net` cosmetic filters if we are dealing with a // collapsible type: any of the cached entries could be a resource on the // target page. - let srcHostname = details.srcHostname; if ( (srcHostname !== '*') && - (requestType === '*' || requestType === 'image' || requestType === '3p' || requestType === '3p-frame') + ( + requestType === '*' || + requestType === 'image' || + requestType === '3p' || + requestType === '3p-frame' + ) ) { srcHostname = '*'; } @@ -635,3 +658,5 @@ const matchBucket = function(url, hostname, bucket, start) { report: report }; })(); + +/******************************************************************************/