this fixes #1013, #1062 (draft)

This commit is contained in:
gorhill 2015-03-27 13:00:55 -04:00
parent 5f8fd22920
commit f2ff0edfaf
18 changed files with 496 additions and 124 deletions

View File

@ -55,6 +55,8 @@ vAPI.app.restart = function() {
/******************************************************************************/
// chrome.storage.local.get(null, function(bin){ console.debug('%o', bin); });
vAPI.storage = chrome.storage.local;
/******************************************************************************/
@ -74,6 +76,7 @@ vAPI.noTabId = '-1';
vAPI.tabs.registerListeners = function() {
var onNavigationClient = this.onNavigation || noopFunc;
var onPopupClient = this.onPopup || noopFunc;
var onUpdatedClient = this.onUpdated || noopFunc;
// https://developer.chrome.com/extensions/webNavigation
// [onCreatedNavigationTarget ->]
@ -160,6 +163,13 @@ vAPI.tabs.registerListeners = function() {
popupCandidateTest(details);
};
var onUpdated = function(tabId, changeInfo, tab) {
if ( changeInfo.url && popupCandidateTest({ tabId: tabId, url: changeInfo.url }) ) {
return;
}
onUpdatedClient(tabId, changeInfo, tab);
};
var onCommitted = function(details) {
if ( details.frameId !== 0 ) {
return;
@ -175,10 +185,7 @@ vAPI.tabs.registerListeners = function() {
chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget);
chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
chrome.webNavigation.onCommitted.addListener(onCommitted);
if ( typeof this.onUpdated === 'function' ) {
chrome.tabs.onUpdated.addListener(this.onUpdated);
}
chrome.tabs.onUpdated.addListener(onUpdated);
if ( typeof this.onClosed === 'function' ) {
chrome.tabs.onRemoved.addListener(this.onClosed);
@ -308,6 +315,37 @@ vAPI.tabs.open = function(details) {
/******************************************************************************/
// Replace the URL of a tab. Noop if the tab does not exist.
vAPI.tabs.replace = function(tabId, url) {
var targetURL = url;
if ( typeof targetURL !== 'string' || targetURL === '' ) {
return;
}
// extension pages
if ( /^[\w-]{2,}:/.test(targetURL) !== true ) {
targetURL = vAPI.getURL(targetURL);
}
if ( typeof tabId !== 'number' ) {
tabId = parseInt(tabId, 10);
if ( isNaN(tabId) ) {
return;
}
}
chrome.tabs.update(tabId, { url: targetURL }, function() {
// this prevent console error
if ( chrome.runtime.lastError ) {
return;
}
});
};
/******************************************************************************/
vAPI.tabs.remove = function(tabId) {
var onTabRemoved = function() {
if ( vAPI.lastError() ) {

View File

@ -710,6 +710,24 @@ vAPI.tabs.open = function(details) {
/******************************************************************************/
// Replace the URL of a tab. Noop if the tab does not exist.
vAPI.tabs.replace = function(tabId, url) {
var targetURL = url;
// extension pages
if ( /^[\w-]{2,}:/.test(targetURL) !== true ) {
targetURL = vAPI.getURL(targetURL);
}
var tab = this.getTabsForIds(tabId);
if ( tab ) {
getBrowserForTab(tab).loadURI(targetURL);
}
};
/******************************************************************************/
vAPI.tabs._remove = function(tab, tabBrowser) {
if ( vAPI.fennec ) {
tabBrowser.closeTab(tab);
@ -1138,18 +1156,13 @@ var httpObserver = {
return true;
}
if ( result.redirectUrl ) {
if ( type === 'main_frame' ) {
channel.cancel(this.ABORT);
vAPI.tabs.open({ tabId: details.tabId, url: result.redirectUrl });
return true;
}
/*channel.redirectionLimit = 1;
/*if ( result.redirectUrl ) {
channel.redirectionLimit = 1;
channel.redirectTo(
Services.io.newURI(result.redirectUrl, null, null)
);
return true;*/
}
return true;
}*/
return false;
},

View File

@ -75,85 +75,13 @@
"message":"Go to request log",
"description":"English: Go to request log"
},
"popupSiteInlineScriptEnabled":{
"message":"Inline <code>script<\/code> tags are <b>allowed<\/b> on this site",
"description":""
"popupTipDoBlockAllPopups":{
"message":"Block all popups for this site",
"description":"English: Block all popups for this site"
},
"popupSiteInlineScriptDisabled":{
"message":"Inline <code>script<\/code> tags are <b>blocked<\/b> on this site",
"description":""
},
"popupSite1pScriptEnabled":{
"message":"1st-party scripts are <b>allowed<\/b> on this site",
"description":""
},
"popupSite1pScriptDisabled":{
"message":"1st-party scripts are <b>blocked<\/b> on this site",
"description":""
},
"popupSite3pScriptEnabled":{
"message":"3rd-party scripts are <b>allowed<\/b> on this site",
"description":""
},
"popupSite3pScriptDisabled":{
"message":"3rd-party scripts are <b>blocked<\/b> on this site",
"description":""
},
"popupSite1pFrameEnabled":{
"message":"1st-party frames are <b>allowed<\/b> on this site",
"description":""
},
"popupSite1pFrameDisabled":{
"message":"1st-party frames are <b>blocked<\/b> on this site",
"description":""
},
"popupSite3pFrameEnabled":{
"message":"3rd-party frames are <b>allowed<\/b> on this site",
"description":""
},
"popupSite3pFrameDisabled":{
"message":"3rd-party frames are <b>blocked<\/b> on this site",
"description":""
},
"popupDefaultInlineScriptEnabled":{
"message":"Inline <code>script</code> tags are <b>allowed<\/b> everywhere by default",
"description":""
},
"popupDefaultInlineScriptDisabled":{
"message":"Inline <code>script</code> tags are <b>blocked<\/b> everywhere by default",
"description":""
},
"popupDefault1pScriptEnabled":{
"message":"1st-party scripts are <b>allowed<\/b> everywhere by default",
"description":""
},
"popupDefault1pScriptDisabled":{
"message":"1st-party scripts are <b>blocked<\/b> everywhere by default",
"description":""
},
"popupDefault3pScriptEnabled":{
"message":"3rd-party scripts are <b>allowed<\/b> everywhere by default",
"description":""
},
"popupDefault3pScriptDisabled":{
"message":"3rd-party scripts are <b>blocked<\/b> everywhere by default",
"description":""
},
"popupDefault1pFrameEnabled":{
"message":"1st-party frames are <b>allowed<\/b> everywhere by default",
"description":""
},
"popupDefault1pFrameDisabled":{
"message":"1st-party frames are <b>blocked<\/b> everywhere by default",
"description":""
},
"popupDefault3pFrameEnabled":{
"message":"3rd-party frames are <b>allowed<\/b> everywhere by default",
"description":""
},
"popupDefault3pFrameDisabled":{
"message":"3rd-party frames are <b>blocked<\/b> everywhere by default",
"description":""
"popupTipDontBlockDoc":{
"message":"Disable strict blocking for this site",
"description":"English: Disable strict blocking for this site"
},
"popupAnyRulePrompt":{
"message":"all",

View File

@ -19,6 +19,7 @@
<script src="js/dynamic-net-filtering.js"></script>
<script src="js/static-net-filtering.js"></script>
<script src="js/cosmetic-filtering.js"></script>
<script src="js/hnswitches.js"></script>
<script src="js/ublock.js"></script>
<script src="js/messaging.js"></script>
<script src="js/profiler.js"></script>

View File

@ -25,6 +25,7 @@ body:not(.advancedUser) [data-tip]:after {
box-shadow: 1px 1px 3px gray;
color: black;
content: attr(data-tip);
display: none;
font: 12px sans-serif;
left: 0;
line-height: 130%;
@ -38,7 +39,8 @@ body:not(.advancedUser) [data-tip]:after {
pointer-events: none;
opacity: 0;
}
[data-tip]:hover:after {
body [data-tip]:hover:after {
display: initial;
opacity: 1 !important;
-webkit-transition: opacity 0.2s 0.4s;
transition: opacity 0.2s 0.4s;
@ -60,6 +62,13 @@ body[dir=rtl] [data-tip][data-tip-anchor="top"]:hover:after {
right: -500%;
}
body [data-tip][data-tip-anchor="topcenter"]:hover:after {
bottom: 140%;
left: -225%;
right: -225%;
top: auto;
}
.hiddenFileInput {
visibility: hidden;
width: 0;

View File

@ -80,7 +80,7 @@ body[dir="rtl"] #panes > div:nth-of-type(2) {
}
#panes > div:nth-of-type(1) {
min-width: 150px;
padding: 4px 1px;
padding: 0;
}
p {
text-align: center;
@ -131,6 +131,33 @@ body.off #switch .fa {
.tool:hover {
color: #444;
}
#extraTools {
background-color: #eee;
border: 0;
color: #aaa;
font-weight: normal;
margin: 1em 0 0 0;
padding: 4px 0 2px 0;
text-align: center;
}
#extraTools > span {
cursor: pointer;
font-size: 18px;
margin: 0 0.5em;
position: relative;
}
#extraTools > span.on > span {
color: #e00;
font-size: 20px;
left: 0;
position: absolute;
text-align: center;
top: 0;
width: 100%;
}
#extraTools > span.on > span:after {
content: '\2715';
}
body.advancedUser h2 {
cursor: pointer;

View File

@ -2,6 +2,7 @@
<html>
<head>
<title></title>
<link rel="stylesheet" href="css/common.css" type="text/css">
<style>
body {
font-family: sans-serif;
@ -33,21 +34,22 @@ button {
padding: 0.25em 0.5em;
font-size: inherit;
}
img {
height: 60vh;
left: 10vw;
opacity: 0.05;
#warningSign {
margin: 1e, 0;
opacity: 1;
pointer-events: none;
position: fixed;
bottom: 5vh;
width: 80vw;
width: 100%;
}
#warningSign > span {
color: #f2a500;
font-size: 180px;
}
</style>
</head>
<body>
<!-- http://commons.wikimedia.org/wiki/File:Caution_sign_used_on_roads_pn.svg
Public domain. I removed the shadow.
--><img src="img/Caution_sign_used_on_roads_pn.svg" />
--><div id="warningSign"><span class="fa">&#xf071;</span></div>
<div>
<p data-i18n="docblockedPrompt1"></p>
<p class="what code"></p>

View File

@ -57,7 +57,6 @@ return {
autoUpdate: true,
collapseBlocked: true,
contextMenuEnabled: true,
dynamicFilteringString: '',
dynamicFilteringEnabled: false,
experimentalEnabled: false,
externalLists: defaultExternalLists,
@ -88,7 +87,7 @@ return {
// read-only
systemSettings: {
compiledMagic: 'squafjaywuba',
compiledMagic: 'perhodsoahya',
selfieMagic: 'spqmeuaftfra'
},

283
src/js/hnswitches.js Normal file
View File

@ -0,0 +1,283 @@
/*******************************************************************************
uBlock - a Chromium browser extension to black/white list requests.
Copyright (C) 2015 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/uBlock
*/
/* global punycode, µBlock */
/* jshint bitwise: false */
/******************************************************************************/
µBlock.HnSwitches = (function() {
'use strict';
/******************************************************************************/
var HnSwitches = function() {
this.reset();
};
/******************************************************************************/
var switchBitOffsets = {
'dontBlockDoc': 0,
'doBlockAllPopups': 2
};
var switchStateToNameMap = {
'1': 'true',
'2': 'false'
};
var nameToSwitchStateMap = {
'true': 1,
'false': 2
};
/******************************************************************************/
// For performance purpose, as simple tests as possible
var reHostnameVeryCoarse = /[g-z_-]/;
var reIPv4VeryCoarse = /\.\d+$/;
// http://tools.ietf.org/html/rfc5952
// 4.3: "MUST be represented in lowercase"
// Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers
var isIPAddress = function(hostname) {
if ( reHostnameVeryCoarse.test(hostname) ) {
return false;
}
if ( reIPv4VeryCoarse.test(hostname) ) {
return true;
}
return hostname.charAt(0) === '[';
};
/******************************************************************************/
var toBroaderHostname = function(hostname) {
if ( hostname === '*' ) {
return '';
}
if ( isIPAddress(hostname) ) {
return '*';
}
var pos = hostname.indexOf('.');
if ( pos === -1 ) {
return '*';
}
return hostname.slice(pos + 1);
};
HnSwitches.toBroaderHostname = toBroaderHostname;
/******************************************************************************/
HnSwitches.prototype.reset = function() {
this.switches = {};
};
/******************************************************************************/
// If value is undefined, the switch is removed
HnSwitches.prototype.toggle = function(switchName, hostname, newVal) {
var bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) {
return false;
}
if ( newVal === this.evaluate(switchName, hostname) ) {
return false;
}
var bits = this.switches[hostname] || 0;
bits &= ~(3 << bitOffset);
bits |= newVal << bitOffset;
if ( bits === 0 ) {
delete this.switches[hostname];
} else {
this.switches[hostname] = bits;
}
return true;
};
/******************************************************************************/
HnSwitches.prototype.toggleZ = function(switchName, hostname, newState) {
var bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) {
return false;
}
var state = this.evaluateZ(switchName, hostname);
if ( newState === state ) {
return false;
}
if ( newState === undefined ) {
newState = !state;
}
var bits = this.switches[hostname] || 0;
bits &= ~(3 << bitOffset);
if ( bits === 0 ) {
delete this.switches[hostname];
} else {
this.switches[hostname] = bits;
}
state = this.evaluateZ(switchName, hostname);
if ( state === newState ) {
return true;
}
this.switches[hostname] = bits | ((newState ? 1 : 2) << bitOffset);
return true;
};
/******************************************************************************/
// 0 = inherit from broader scope, up to default state
// 1 = non-default state
// 2 = forced default state (to override a broader non-default state)
HnSwitches.prototype.evaluate = function(switchName, hostname) {
var bits = this.switches[hostname] || 0;
if ( bits === 0 ) {
return 0;
}
var bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) {
return 0;
}
return (bits >> bitOffset) & 3;
};
/******************************************************************************/
HnSwitches.prototype.evaluateZ = function(switchName, hostname) {
var bitOffset = switchBitOffsets[switchName];
if ( bitOffset === undefined ) {
return false;
}
var bits;
var s = hostname;
for (;;) {
bits = this.switches[s] || 0;
if ( bits !== 0 ) {
bits = bits >> bitOffset & 3;
if ( bits !== 0 ) {
return bits === 1;
}
}
s = toBroaderHostname(s);
if ( s === '' ) {
break;
}
}
return false;
};
/******************************************************************************/
HnSwitches.prototype.toString = function() {
var out = [];
var switchName, val;
var hostname;
for ( hostname in this.switches ) {
if ( this.switches.hasOwnProperty(hostname) === false ) {
continue;
}
for ( switchName in switchBitOffsets ) {
if ( switchBitOffsets.hasOwnProperty(switchName) === false ) {
continue;
}
val = this.evaluate(switchName, hostname);
if ( val === 0 ) {
continue;
}
out.push(switchName + ': ' + hostname + ' ' + switchStateToNameMap[val]);
}
}
return out.join('\n');
};
/******************************************************************************/
HnSwitches.prototype.fromString = function(text) {
var textEnd = text.length;
var lineBeg = 0, lineEnd;
var line, pos;
var fields;
var switchName, hostname, state;
while ( lineBeg < textEnd ) {
lineEnd = text.indexOf('\n', lineBeg);
if ( lineEnd < 0 ) {
lineEnd = text.indexOf('\r', lineBeg);
if ( lineEnd < 0 ) {
lineEnd = textEnd;
}
}
line = text.slice(lineBeg, lineEnd).trim();
lineBeg = lineEnd + 1;
pos = line.indexOf('# ');
if ( pos !== -1 ) {
line = line.slice(0, pos).trim();
}
if ( line === '' ) {
continue;
}
fields = line.split(/\s+/);
if ( fields.length !== 3 ) {
continue;
}
switchName = fields[0];
pos = switchName.indexOf(':');
if ( pos === -1 ) {
continue;
}
switchName = switchName.slice(0, pos);
if ( switchBitOffsets.hasOwnProperty(switchName) === false ) {
continue;
}
hostname = punycode.toASCII(fields[1]);
state = fields[2];
if ( nameToSwitchStateMap.hasOwnProperty(state) === false ) {
continue;
}
this.toggle(switchName, hostname, nameToSwitchStateMap[state]);
}
};
/******************************************************************************/
return HnSwitches;
/******************************************************************************/
})();
/******************************************************************************/
µBlock.hnSwitches = new µBlock.HnSwitches();
/******************************************************************************/

View File

@ -88,6 +88,10 @@ var onMessage = function(request, sender, callback) {
µb.selectFilterLists(request.switches);
break;
case 'toggleHostnameSwitch':
µb.toggleHostnameSwitch(request);
break;
case 'userSettings':
response = µb.changeUserSettings(request.name, request.value);
break;
@ -229,6 +233,8 @@ var getStats = function(tabId, tabTitle) {
r.firewallRules = getFirewallRules(pageStore.pageHostname, r.hostnameDict);
r.canElementPicker = r.pageHostname.indexOf('.') !== -1;
r.canRequestLog = canRequestLog;
r.doBlockAllPopups = µb.hnSwitches.evaluateZ('doBlockAllPopups', r.pageHostname);
r.dontBlockDoc = µb.hnSwitches.evaluateZ('dontBlockDoc', r.pageHostname);
} else {
r.hostnameDict = {};
r.firewallRules = getFirewallRules();
@ -1007,6 +1013,8 @@ var backupUserData = function(callback) {
userSettings: µb.userSettings,
filterLists: µb.remoteBlacklists,
netWhitelist: µb.stringFromWhitelist(µb.netWhitelist),
dynamicFilteringString: µb.permanentFirewall.toString(),
hostnameSwitchesString: µb.hnSwitches.toString(),
userFilters: details.content
};
var now = new Date();
@ -1033,7 +1041,7 @@ var backupUserData = function(callback) {
var restoreUserData = function(request) {
var userData = request.userData;
var countdown = 5;
var countdown = 7;
var onCountdown = function() {
countdown -= 1;
if ( countdown === 0 ) {
@ -1047,9 +1055,15 @@ var restoreUserData = function(request) {
µBlock.saveLocalSettings(true);
µb.XAL.keyvalSetMany(userData.userSettings, onCountdown);
µb.XAL.keyvalSetOne('remoteBlacklists', userData.filterLists, onCountdown);
µb.XAL.keyvalSetOne('netWhitelist', userData.netWhitelist, onCountdown);
µb.assets.put('assets/user/filters.txt', userData.userFilters, onCountdown);
µb.XAL.keyvalSetOne('netWhitelist', userData.netWhitelist || '', onCountdown);
// With versions 0.9.2.4-, dynamic rules were saved within the
// `userSettings` object. No longer the case.
var s = userData.dynamicFilteringString || userData.userSettings.dynamicFilteringString || '';
µb.XAL.keyvalSetOne('dynamicFilteringString', s, onCountdown);
µb.XAL.keyvalSetOne('hostnameSwitchesString', userData.hostnameSwitchesString || '', onCountdown);
µb.assets.put('assets/user/filters.txt', userData.userFilters, onCountdown);
µb.XAL.keyvalSetMany({
lastRestoreFile: request.file || '',
lastRestoreTime: Date.now(),

View File

@ -429,6 +429,10 @@ var renderPopup = function() {
// This will collate all domains, touched or not
renderPrivacyExposure();
// Extra tools
uDom('#doBlockAllPopups').toggleClass('on', popupData.doBlockAllPopups === true);
uDom('#dontBlockDoc').toggleClass('on', popupData.dontBlockDoc === true);
// https://github.com/gorhill/uBlock/issues/470
// This must be done here, to be sure the popup is resized properly
var dfPaneVisible = popupData.dfEnabled && popupData.advancedUserEnabled;
@ -651,6 +655,23 @@ var saveFirewallRules = function() {
/******************************************************************************/
var toggleHostnameSwitch = function() {
var elem = uDom(this);
var switchName = elem.attr('id');
if ( !switchName ) {
return;
}
elem.toggleClass('on');
messager.send({
what: 'toggleHostnameSwitch',
name: switchName,
hostname: popupData.pageHostname,
state: elem.hasClass('on')
});
};
/******************************************************************************/
// Poll for changes.
//
// I couldn't find a better way to be notified of changes which can affect
@ -733,6 +754,7 @@ uDom.onLoad(function () {
uDom('a[href]').on('click', gotoURL);
uDom('h2').on('click', toggleFirewallPane);
uDom('#refresh').on('click', reloadTab);
uDom('.hnSwitch').on('click', toggleHostnameSwitch);
uDom('#saveRules').on('click', saveFirewallRules);
uDom('[data-i18n="popupAnyRulePrompt"]').on('click', toggleMinimize);
});

View File

@ -135,8 +135,9 @@ var onUserSettingsReady = function(fetched) {
µb.mirrors.toggle(false /* userSettings.experimentalEnabled */);
µb.contextMenu.toggle(userSettings.contextMenuEnabled);
µb.permanentFirewall.fromString(userSettings.dynamicFilteringString);
µb.permanentFirewall.fromString(fetched.dynamicFilteringString);
µb.sessionFirewall.assign(µb.permanentFirewall);
µb.hnSwitches.fromString(fetched.hostnameSwitchesString);
// Remove obsolete setting
delete userSettings.logRequests;
@ -214,6 +215,8 @@ return function() {
var fetchableProps = {
'compiledMagic': '',
'dynamicFilteringString': '',
'hostnameSwitchesString': '',
'lastRestoreFile': '',
'lastRestoreTime': 0,
'lastBackupFile': '',

View File

@ -63,7 +63,6 @@ var typeNameToTypeValue = {
'xmlhttprequest': 5 << 4,
'sub_frame': 6 << 4,
'other': 7 << 4,
'main_frame': 12 << 4,
'cosmetic-filtering': 13 << 4,
'inline-script': 14 << 4,
'popup': 15 << 4
@ -2117,7 +2116,7 @@ FilterContainer.prototype.matchString = function(context) {
// Use exact type match for anything beyond `other`
// Also, be prepared to support unknown types
var type = typeNameToTypeValue[context.requestType] || typeOtherValue;
if ( type > (7 << 4) ) {
if ( type > typeOtherValue ) {
return this.matchStringExactType(context, context.requestURL, context.requestType);
}

View File

@ -70,8 +70,13 @@
/******************************************************************************/
µBlock.savePermanentFirewallRules = function() {
this.userSettings.dynamicFilteringString = this.permanentFirewall.toString();
this.XAL.keyvalSetOne('dynamicFilteringString', this.userSettings.dynamicFilteringString);
this.XAL.keyvalSetOne('dynamicFilteringString', this.permanentFirewall.toString());
};
/******************************************************************************/
µBlock.saveHostnameSwitches = function() {
this.XAL.keyvalSetOne('hostnameSwitchesString', this.hnSwitches.toString());
};
/******************************************************************************/

View File

@ -111,11 +111,26 @@ vAPI.tabs.onPopup = function(details) {
};
var targetURL = details.targetURL;
// If the page URL is that of our "blocked page" URL, extract the URL of
// the page which was blocked.
if ( targetURL.lastIndexOf(vAPI.getURL('document-blocked.html'), 0) === 0 ) {
var matches = /details=([^&]+)/.exec(targetURL);
if ( matches !== null ) {
targetURL = JSON.parse(atob(matches[1])).url;
}
}
var result = '';
// Check user switch first
if ( µb.hnSwitches.evaluateZ('doBlockAllPopups', openerHostname) ) {
result = 'ub:doBlockAllPopups true';
}
// https://github.com/gorhill/uBlock/issues/323
// If popup URL is whitelisted, do not block it
if ( µb.getNetFilteringSwitch(targetURL) ) {
if ( result === '' && µb.getNetFilteringSwitch(targetURL) ) {
result = µb.staticNetFilteringEngine.matchStringExactType(context, targetURL, 'popup');
}

View File

@ -199,11 +199,18 @@ var onBeforeRootFrameRequest = function(details) {
var result = '';
// Permanently unrestricted?
if ( result === '' && µb.hnSwitches.evaluateZ('dontBlockDoc', requestHostname) ) {
result = 'ua:dontBlockDoc true';
}
// Temporarily whitelisted?
var obsolete = documentWhitelists[requestHostname];
if ( obsolete !== undefined ) {
if ( obsolete > Date.now() ) {
result = 'da:*' + ' ' + requestHostname + ' doc allow';
if ( result === '' ) {
result = 'ta:*' + ' ' + requestHostname + ' doc allow';
}
} else {
delete documentWhitelists[requestHostname];
}
@ -211,15 +218,7 @@ var onBeforeRootFrameRequest = function(details) {
// Filtering
if ( result === '' && µb.getNetFilteringSwitch(requestURL) ) {
if ( µb.userSettings.advancedUserEnabled ) {
var df = µb.sessionFirewall.evaluateCellZY(requestHostname, requestHostname, '*');
if ( df.mustBlockOrAllow() ) {
result = df.toFilterString();
}
}
if ( result === '' ) {
result = µb.staticNetFilteringEngine.matchString(context);
}
result = µb.staticNetFilteringEngine.matchString(context);
}
// Log
@ -236,9 +235,12 @@ var onBeforeRootFrameRequest = function(details) {
// Blocked
var query = btoa(JSON.stringify({
url: requestURL,
why: result + '$document'
why: result
}));
return { redirectUrl: vAPI.getURL('document-blocked.html?details=') + query };
vAPI.tabs.replace(details.tabId, vAPI.getURL('document-blocked.html?details=') + query);
return { cancel: true };
};
/******************************************************************************/

View File

@ -318,4 +318,12 @@ var matchWhitelistDirective = function(url, hostname, directive) {
/******************************************************************************/
µBlock.toggleHostnameSwitch = function(details) {
if ( this.hnSwitches.toggleZ(details.name, details.hostname, details.state) ) {
this.saveHostnameSwitches();
}
};
/******************************************************************************/
})();

View File

@ -26,6 +26,10 @@
<p class="statValue" id="total-blocked">?</p>
<h2 data-i18n="popupHitDomainCountPrompt">&nbsp;</h2>
<p class="statValue" id="popupHitDomainCount">&nbsp;</p>
<div id="extraTools">
<span id="doBlockAllPopups" class="hnSwitch fa" data-i18n-tip="popupTipDoBlockAllPopups" data-tip-anchor="topcenter">&#xf0c5;<span></span></span>
<span id="dontBlockDoc" class="hnSwitch fa" data-i18n-tip="popupTipDontBlockDoc" data-tip-anchor="topcenter">&#xf071;<span></span></span>
</div>
<div id="refresh" class="fa">&#xf021;</div>
</div><!-- DO NOT REMOVE --><div>
<div id="firewallContainer">