diff --git a/src/js/document-blocked.js b/src/js/document-blocked.js index 93e2808ca..969017ac4 100644 --- a/src/js/document-blocked.js +++ b/src/js/document-blocked.js @@ -73,7 +73,7 @@ var proceedPermanent = function() { what: 'toggleHostnameSwitch', name: 'noStrictBlocking', hostname: getTargetHostname(), - fromHostname: details.hn, + deep: true, state: true }, proceedToURL); }; diff --git a/src/js/hnswitches.js b/src/js/hnswitches.js index 27a82bc59..1ca46b3c5 100644 --- a/src/js/hnswitches.js +++ b/src/js/hnswitches.js @@ -126,7 +126,7 @@ HnSwitches.prototype.toggle = function(switchName, hostname, newVal) { /******************************************************************************/ -HnSwitches.prototype.toggleZ = function(switchName, hostname, newState) { +HnSwitches.prototype.toggleOneZ = function(switchName, hostname, newState) { var bitOffset = switchBitOffsets[switchName]; if ( bitOffset === undefined ) { return false; @@ -155,6 +155,47 @@ HnSwitches.prototype.toggleZ = function(switchName, hostname, newState) { /******************************************************************************/ +HnSwitches.prototype.toggleBranchZ = function(switchName, targetHostname, newState) { + var changed = this.toggleOneZ(switchName, targetHostname, newState); + + var targetLen = targetHostname.length; + var hostnames = []; + + for ( var hostname in this.switches ) { + if ( this.switches.hasOwnProperty(hostname) === false ) { + continue; + } + if ( hostname === targetHostname ) { + continue; + } + if ( hostname.length <= targetLen ) { + continue; + } + if ( hostname.slice(-targetLen) !== targetHostname ) { + continue; + } + if ( hostname.charAt(hostname.length - targetLen - 1) !== '.' ) { + continue; + } + hostnames.push(hostname); + } + + // Decreasing length order so that all switch states are inherited from + // targetHostname. + hostnames.sort(function(a, b) { + return b.length - a.length; + }); + + var i = hostnames.length; + while ( i-- ) { + changed = this.toggleOneZ(switchName, hostnames[i], newState) || changed; + } + + return changed; +}; + +/******************************************************************************/ + // 0 = inherit from broader scope, up to default state // 1 = non-default state // 2 = forced default state (to override a broader non-default state) diff --git a/src/js/ublock.js b/src/js/ublock.js index 7cc9781d2..329724ec4 100644 --- a/src/js/ublock.js +++ b/src/js/ublock.js @@ -319,29 +319,12 @@ var matchWhitelistDirective = function(url, hostname, directive) { /******************************************************************************/ µBlock.toggleHostnameSwitch = function(details) { - var hostname = details.hostname; - var fromHostname = details.fromHostname || hostname; var changed = false; - var fromHostnames = []; - var pos; - for (;;) { - fromHostnames.push(fromHostname); - if ( fromHostname === hostname ) { - break; - } - pos = fromHostname.indexOf('.'); - if ( pos === -1 ) { - break; - } - fromHostname = fromHostname.slice(pos + 1); - } - - var i = fromHostnames.length; - while ( i-- ) { - if ( this.hnSwitches.toggleZ(details.name, fromHostnames[i], details.state) ) { - changed = true; - } + if ( details.deep === true ) { + changed = this.hnSwitches.toggleBranchZ(details.name, details.hostname, details.state); + } else { + changed = this.hnSwitches.toggleOneZ(details.name, details.hostname, details.state); } if ( changed ) {