mirror of https://github.com/gorhill/uBlock.git
parent
5f8fd22920
commit
f2ff0edfaf
|
@ -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() ) {
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"></span></div>
|
||||
<div>
|
||||
<p data-i18n="docblockedPrompt1"></p>
|
||||
<p class="what code"></p>
|
||||
|
|
|
@ -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'
|
||||
},
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
/******************************************************************************/
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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': '',
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
<p class="statValue" id="total-blocked">?</p>
|
||||
<h2 data-i18n="popupHitDomainCountPrompt"> </h2>
|
||||
<p class="statValue" id="popupHitDomainCount"> </p>
|
||||
<div id="extraTools">
|
||||
<span id="doBlockAllPopups" class="hnSwitch fa" data-i18n-tip="popupTipDoBlockAllPopups" data-tip-anchor="topcenter"><span></span></span>
|
||||
<span id="dontBlockDoc" class="hnSwitch fa" data-i18n-tip="popupTipDontBlockDoc" data-tip-anchor="topcenter"><span></span></span>
|
||||
</div>
|
||||
<div id="refresh" class="fa"></div>
|
||||
</div><!-- DO NOT REMOVE --><div>
|
||||
<div id="firewallContainer">
|
||||
|
|
Loading…
Reference in New Issue