mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-02 00:42:45 +01:00
too many changes for #433: branching so that I can commit and keep working on it
This commit is contained in:
parent
aed66e5278
commit
1fe7045b92
@ -16,7 +16,8 @@
|
|||||||
<script src="js/liquid-dict.js"></script>
|
<script src="js/liquid-dict.js"></script>
|
||||||
<script src="js/utils.js"></script>
|
<script src="js/utils.js"></script>
|
||||||
<script src="js/assets.js"></script>
|
<script src="js/assets.js"></script>
|
||||||
<script src="js/net-filtering.js"></script>
|
<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/cosmetic-filtering.js"></script>
|
||||||
<script src="js/ublock.js"></script>
|
<script src="js/ublock.js"></script>
|
||||||
<script src="js/messaging.js"></script>
|
<script src="js/messaging.js"></script>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
font: 13px sans-serif;
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
min-width: 180px;
|
border: 0;
|
||||||
overflow: hidden;
|
|
||||||
float: left;
|
float: left;
|
||||||
|
font: 13px sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
h1,h2,h3,h4 {
|
h1,h2,h3,h4 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -30,7 +30,13 @@ a {
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
body > div {
|
body > div {
|
||||||
padding: 4px 12px 0 12px;
|
background-color: transparent;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
body > div:nth-of-type(2) {
|
||||||
|
padding: 4px 12px 0 5px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
@ -53,6 +59,9 @@ p {
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
[data-i18n="popupBlockedRequestPrompt"] {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
#page-blocked {
|
#page-blocked {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
@ -80,6 +89,20 @@ p {
|
|||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#dynamicFilteringToggler {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#dynamicFilteringToggler::before {
|
||||||
|
color: gray;
|
||||||
|
content: '+\202F';
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
body.dynamicFilteringEnabled #dynamicFilteringToggler::before {
|
||||||
|
content: '\2212\202F';
|
||||||
|
}
|
||||||
|
|
||||||
.dynamicFiltering div > .tip {
|
.dynamicFiltering div > .tip {
|
||||||
background-color: #fffff4;
|
background-color: #fffff4;
|
||||||
border: 1px solid #888;
|
border: 1px solid #888;
|
||||||
@ -105,157 +128,67 @@ p {
|
|||||||
font: normal monospace;
|
font: normal monospace;
|
||||||
padding: 1px 0;
|
padding: 1px 0;
|
||||||
}
|
}
|
||||||
#dynamicFilteringToggler {
|
|
||||||
margin: 0;
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler.hasBlock:not(.on) {
|
|
||||||
background-color: #fbb;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler > div {
|
|
||||||
font-size: 9px;
|
|
||||||
line-height: 100%;
|
|
||||||
color: #888;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 25%;
|
|
||||||
display: none;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler.on:hover > div {
|
|
||||||
display: initial;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler > div:nth-of-type(1) {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler > div:nth-of-type(2) {
|
|
||||||
left: 25%;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler > div:nth-of-type(3) {
|
|
||||||
left: 50%;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler > div:nth-of-type(4) {
|
|
||||||
left: 75%;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler > a {
|
|
||||||
padding: 0 2px 0 8px;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
color: #666;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
body[dir=rtl] #dynamicFilteringToggler > a {
|
|
||||||
right: auto;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#dynamicFilteringToggler a:hover {
|
|
||||||
color: #444;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler.on:hover a {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler::before {
|
|
||||||
content: '\f107';
|
|
||||||
}
|
|
||||||
#dynamicFilteringToggler.on::before {
|
|
||||||
content: '\f106';
|
|
||||||
}
|
|
||||||
#dynamicFilteringContainer {
|
#dynamicFilteringContainer {
|
||||||
margin: 0;
|
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 0;
|
direction: rtl;
|
||||||
display: none;
|
font-size: 12px;
|
||||||
}
|
|
||||||
#dynamicFilteringToggler.on + #dynamicFilteringContainer {
|
|
||||||
display: initial;
|
|
||||||
}
|
|
||||||
.dynamicFiltering {
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
text-align: right;
|
||||||
|
width: 7px;
|
||||||
|
}
|
||||||
|
body.dynamicFilteringEnabled #dynamicFilteringContainer {
|
||||||
|
display: block;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
#dynamicFilteringContainer > div {
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 0;
|
direction: ltr;
|
||||||
height: 2.75em;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.dynamicFiltering.local {
|
|
||||||
border-bottom: 1px solid white;
|
|
||||||
}
|
|
||||||
.dynamicFiltering.global {
|
|
||||||
height: 1.25em;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div {
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 1px solid #e6e6e6;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
width: 200px;
|
||||||
background-color: #e6e6e6;
|
|
||||||
position: absolute;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
.dynamicFiltering > div:not(:first-child) {
|
#dynamicFilteringContainer > div > span {
|
||||||
border-left: 1px solid white !important;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div:nth-of-type(1) {
|
|
||||||
left: 0;
|
|
||||||
width: 7%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div:nth-of-type(2) {
|
|
||||||
left: 7%;
|
|
||||||
width: 18%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div:nth-of-type(3) {
|
|
||||||
left: 25%;
|
|
||||||
width: 25%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div:nth-of-type(4) {
|
|
||||||
left: 50%;
|
|
||||||
width: 25%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div:nth-of-type(5) {
|
|
||||||
left: 75%;
|
|
||||||
width: 25%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div:nth-of-type(6) {
|
|
||||||
left: 0;
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div:nth-of-type(7) {
|
|
||||||
left: 50%;
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
.dynamicFiltering > div.label {
|
|
||||||
margin: 0;
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
color: black;
|
|
||||||
opacity: 0.4;
|
|
||||||
font: 12px monospace;
|
|
||||||
text-align: center;
|
|
||||||
top: 50%;
|
|
||||||
-webkit-transform: translateY(-50%);
|
|
||||||
transform: translateY(-50%);
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: gray;
|
||||||
|
display: inline-block;
|
||||||
|
height: 2em;
|
||||||
|
line-height: 2em;
|
||||||
|
pointer-events: none;
|
||||||
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
.dynamicFiltering > div.blocked {
|
body.dynamicFilteringEnabled #dynamicFilteringContainer > div > span {
|
||||||
border-color: #fbb;
|
background-color: #e6e6e6;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
#dynamicFilteringContainer > div > span:nth-of-type(1) {
|
||||||
|
border-right: 1px solid white;
|
||||||
|
padding-right: 4px;
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
#dynamicFilteringContainer > div > span:nth-of-type(2) {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 9%;
|
||||||
|
}
|
||||||
|
#dynamicFilteringContainer > div > span:nth-of-type(3) {
|
||||||
|
border-left: 1px solid white;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 16%;
|
||||||
|
}
|
||||||
|
body.dynamicFilteringEnabled #dynamicFilteringContainer > div > span:nth-of-type(3) {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
#dynamicFilteringContainer span.blocked[data-src] {
|
||||||
background-color: #fbb;
|
background-color: #fbb;
|
||||||
}
|
}
|
||||||
.dynamicFiltering > div.ownFilter {
|
#dynamicFilteringContainer span.ownFilter[data-src] {
|
||||||
border-color: #bbb;
|
|
||||||
background-color: #bbb;
|
background-color: #bbb;
|
||||||
}
|
}
|
||||||
.dynamicFiltering > div.blocked.ownFilter {
|
#dynamicFilteringContainer span.blocked.ownFilter[data-src] {
|
||||||
border-color: #f66;
|
|
||||||
background-color: #f66;
|
background-color: #f66;
|
||||||
}
|
}
|
@ -55,6 +55,7 @@ return {
|
|||||||
autoUpdate: true,
|
autoUpdate: true,
|
||||||
collapseBlocked: true,
|
collapseBlocked: true,
|
||||||
contextMenuEnabled: true,
|
contextMenuEnabled: true,
|
||||||
|
dynamicFilteringString: '',
|
||||||
dynamicFilteringSelfie: '',
|
dynamicFilteringSelfie: '',
|
||||||
dynamicFilteringEnabled: false,
|
dynamicFilteringEnabled: false,
|
||||||
experimentalEnabled: false,
|
experimentalEnabled: false,
|
||||||
@ -106,7 +107,7 @@ return {
|
|||||||
firstUpdateAfter: 5 * oneMinute,
|
firstUpdateAfter: 5 * oneMinute,
|
||||||
nextUpdateAfter: 7 * oneHour,
|
nextUpdateAfter: 7 * oneHour,
|
||||||
|
|
||||||
selfieMagic: 'odyxfmbsqllh',
|
selfieMagic: 'qidcglrwobsm',
|
||||||
selfieAfter: 7 * oneMinute,
|
selfieAfter: 7 * oneMinute,
|
||||||
|
|
||||||
pageStores: {},
|
pageStores: {},
|
||||||
|
@ -216,7 +216,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
|||||||
var selector;
|
var selector;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
selector = generics[i];
|
selector = generics[i];
|
||||||
if ( injectedSelectors[selector] !== undefined ) {
|
if ( injectedSelectors.hasOwnProperty(selector) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
@ -241,14 +241,14 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
|||||||
if ( !attrValue ) { continue; }
|
if ( !attrValue ) { continue; }
|
||||||
selector = '[' + attr + '="' + attrValue + '"]';
|
selector = '[' + attr + '="' + attrValue + '"]';
|
||||||
if ( generics[selector] ) {
|
if ( generics[selector] ) {
|
||||||
if ( injectedSelectors[selector] === undefined ) {
|
if ( injectedSelectors.hasOwnProperty(selector) === false ) {
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
out.push(selector);
|
out.push(selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selector = node.tagName.toLowerCase() + selector;
|
selector = node.tagName.toLowerCase() + selector;
|
||||||
if ( generics[selector] ) {
|
if ( generics[selector] ) {
|
||||||
if ( injectedSelectors[selector] === undefined ) {
|
if ( injectedSelectors.hasOwnProperty(selector) === false ) {
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
out.push(selector);
|
out.push(selector);
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
|||||||
iSelector = selectors.length;
|
iSelector = selectors.length;
|
||||||
while ( iSelector-- ) {
|
while ( iSelector-- ) {
|
||||||
selector = selectors[iSelector];
|
selector = selectors[iSelector];
|
||||||
if ( injectedSelectors[selector] === undefined ) {
|
if ( injectedSelectors.hasOwnProperty(selector) === false ) {
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
out.push(selector);
|
out.push(selector);
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
|||||||
|
|
||||||
var processHighHighGenerics = function() {
|
var processHighHighGenerics = function() {
|
||||||
processHighHighGenericsTimer = null;
|
processHighHighGenericsTimer = null;
|
||||||
if ( injectedSelectors['{{highHighGenerics}}'] !== undefined ) { return; }
|
if ( injectedSelectors.hasOwnProperty('{{highHighGenerics}}') ) { return; }
|
||||||
if ( document.querySelector(highGenerics.hideHigh) === null ) { return; }
|
if ( document.querySelector(highGenerics.hideHigh) === null ) { return; }
|
||||||
injectedSelectors['{{highHighGenerics}}'] = true;
|
injectedSelectors['{{highHighGenerics}}'] = true;
|
||||||
// We need to filter out possible exception cosmetic filters from
|
// We need to filter out possible exception cosmetic filters from
|
||||||
@ -443,10 +443,10 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( addedNodeListsTimer === null ) {
|
if ( addedNodeListsTimer === null ) {
|
||||||
// I arbitrarily chose 50 ms for now:
|
// I arbitrarily chose 100 ms for now:
|
||||||
// I have to compromise between the overhead of processing too few
|
// I have to compromise between the overhead of processing too few
|
||||||
// nodes too often and the delay of many nodes less often.
|
// nodes too often and the delay of many nodes less often.
|
||||||
addedNodeListsTimer = setTimeout(mutationObservedHandler, 75);
|
addedNodeListsTimer = setTimeout(mutationObservedHandler, 100);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
485
src/js/dynamic-net-filtering.js
Normal file
485
src/js/dynamic-net-filtering.js
Normal file
@ -0,0 +1,485 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
µBlock - a Chromium browser extension to black/white list requests.
|
||||||
|
Copyright (C) 2014 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.dynamicNetFilteringEngine = (function() {
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var magicId = 'chmdgxwtetgu';
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var Matrix = function() {
|
||||||
|
this.reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var typeBitOffsets = {
|
||||||
|
'*': 0,
|
||||||
|
'inline-script': 2,
|
||||||
|
'1p-script': 4,
|
||||||
|
'3p-script': 6,
|
||||||
|
'3p-frame': 8,
|
||||||
|
'image': 10
|
||||||
|
};
|
||||||
|
|
||||||
|
var stateToNameMap = {
|
||||||
|
'1': 'block',
|
||||||
|
'2': 'allow',
|
||||||
|
'3': 'noop'
|
||||||
|
};
|
||||||
|
|
||||||
|
var nameToStateMap = {
|
||||||
|
'block': 1,
|
||||||
|
'allow': 2,
|
||||||
|
'noop': 3
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
};
|
||||||
|
|
||||||
|
Matrix.toBroaderHostname = toBroaderHostname;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.reset = function() {
|
||||||
|
this.r = 0;
|
||||||
|
this.type = '';
|
||||||
|
this.y = '';
|
||||||
|
this.z = '';
|
||||||
|
this.rules = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) {
|
||||||
|
var bitOffset = typeBitOffsets[type];
|
||||||
|
var k = srcHostname + ' ' + desHostname;
|
||||||
|
var oldBitmap = this.rules[k];
|
||||||
|
if ( oldBitmap === undefined ) {
|
||||||
|
oldBitmap = 0;
|
||||||
|
}
|
||||||
|
var newBitmap = oldBitmap & ~(3 << bitOffset) | (state << bitOffset);
|
||||||
|
if ( newBitmap === oldBitmap ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( newBitmap === 0 ) {
|
||||||
|
delete this.rules[k];
|
||||||
|
} else {
|
||||||
|
this.rules[k] = newBitmap;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.blockCell = function(srcHostname, desHostname, type) {
|
||||||
|
this.evaluateCellZY(srcHostname, desHostname, type);
|
||||||
|
if ( this.r === 1 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.setCell(srcHostname, desHostname, type, 0);
|
||||||
|
this.evaluateCellZY(srcHostname, desHostname, type);
|
||||||
|
if ( this.r === 1 ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this.setCell(srcHostname, desHostname, type, 1);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://www.youtube.com/watch?v=Csewb_eIStY
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.allowCell = function(srcHostname, desHostname, type) {
|
||||||
|
this.evaluateCellZY(srcHostname, desHostname, type);
|
||||||
|
if ( this.r === 2 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.setCell(srcHostname, desHostname, type, 0);
|
||||||
|
this.evaluateCellZY(srcHostname, desHostname, type);
|
||||||
|
if ( this.r === 2 ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this.setCell(srcHostname, desHostname, type, 2);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.unsetCell = function(srcHostname, desHostname, type) {
|
||||||
|
this.evaluateCellZY(srcHostname, desHostname, type);
|
||||||
|
if ( this.r === 0 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.setCell(srcHostname, desHostname, type, 0);
|
||||||
|
this.evaluateCellZY(srcHostname, desHostname, type);
|
||||||
|
if ( this.r === 0 || this.r === 3 ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this.setCell(srcHostname, desHostname, type, 3);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.evaluateCell = function(srcHostname, desHostname, type) {
|
||||||
|
var key = srcHostname + ' ' + desHostname;
|
||||||
|
var bitmap = this.rules[key];
|
||||||
|
if ( bitmap === undefined ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return bitmap >> typeBitOffsets[type] & 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.clearRegisters = function() {
|
||||||
|
this.r = 0;
|
||||||
|
this.type = '';
|
||||||
|
this.y = '';
|
||||||
|
this.z = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) {
|
||||||
|
var bitOffset = typeBitOffsets[type];
|
||||||
|
var s = srcHostname;
|
||||||
|
var v;
|
||||||
|
for (;;) {
|
||||||
|
this.z = s;
|
||||||
|
v = this.rules[s + ' ' + desHostname];
|
||||||
|
if ( v !== undefined ) {
|
||||||
|
v = v >> bitOffset & 3;
|
||||||
|
if ( v !== 0 ) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s = toBroaderHostname(s);
|
||||||
|
if ( s === '' ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// srcHostname is '*' at this point
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
|
||||||
|
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
||||||
|
this.type = '';
|
||||||
|
this.r = 0;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
this.type = type;
|
||||||
|
// Specific-hostname specific-type cell
|
||||||
|
this.y = desHostname;
|
||||||
|
this.r = this.evaluateCellZ(srcHostname, desHostname, type);
|
||||||
|
if ( this.r !== 0 ) { return this; }
|
||||||
|
|
||||||
|
var d = desHostname;
|
||||||
|
for (;;) {
|
||||||
|
d = toBroaderHostname(d);
|
||||||
|
if ( d === '*' ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// specific-hostname specific-type cell
|
||||||
|
this.y = d;
|
||||||
|
this.r = this.evaluateCellZ(srcHostname, d, type);
|
||||||
|
if ( this.r !== 0 ) { return this; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any-hostname specific-type cells
|
||||||
|
this.y = '*';
|
||||||
|
this.r = this.evaluateCellZ(srcHostname, '*', type);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// http://youtu.be/gSGk1bQ9rcU?t=25m6s
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.mustBlockOrAllow = function() {
|
||||||
|
return this.r === 1 || this.r === 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.toFilterString = function() {
|
||||||
|
if ( this.type === '' ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if ( this.r === 1 ) {
|
||||||
|
return 'db:' + this.z + ' ' + this.y + ' ' + this.type + ' block';
|
||||||
|
}
|
||||||
|
if ( this.r === 2 ) {
|
||||||
|
return 'da:' + this.z + ' ' + this.y + ' ' + this.type + ' allow';
|
||||||
|
}
|
||||||
|
if ( this.r === 3 ) {
|
||||||
|
return 'dn:' + this.z + ' ' + this.y + ' ' + this.type + ' noop';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.mustBlock = function(srcHostname, desHostname, type) {
|
||||||
|
this.evaluateCellZY(srcHostname, desHostname, type);
|
||||||
|
return this.r === 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.srcHostnameFromRule = function(rule) {
|
||||||
|
return rule.slice(0, rule.indexOf(' '));
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.desHostnameFromRule = function(rule) {
|
||||||
|
return rule.slice(rule.indexOf(' ') + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.toString = function() {
|
||||||
|
var out = [];
|
||||||
|
var rule, type, val;
|
||||||
|
var srcHostname, desHostname;
|
||||||
|
for ( rule in this.rules ) {
|
||||||
|
if ( this.rules.hasOwnProperty(rule) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
srcHostname = this.srcHostnameFromRule(rule);
|
||||||
|
desHostname = this.desHostnameFromRule(rule);
|
||||||
|
for ( type in typeBitOffsets ) {
|
||||||
|
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
val = this.evaluateCell(srcHostname, desHostname, type);
|
||||||
|
if ( val === 0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out.push(
|
||||||
|
punycode.toUnicode(srcHostname) + ' ' +
|
||||||
|
punycode.toUnicode(desHostname) + ' ' +
|
||||||
|
type + ' ' +
|
||||||
|
stateToNameMap[val]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.fromString = function(text, append) {
|
||||||
|
var textEnd = text.length;
|
||||||
|
var lineBeg = 0, lineEnd;
|
||||||
|
var line, pos;
|
||||||
|
var fields, fieldVal;
|
||||||
|
var srcHostname = '';
|
||||||
|
var desHostname = '';
|
||||||
|
var type, 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+/);
|
||||||
|
|
||||||
|
// Less than 2 fields makes no sense
|
||||||
|
if ( fields.length < 2 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldVal = fields[0];
|
||||||
|
|
||||||
|
// Valid rule syntax:
|
||||||
|
|
||||||
|
// srcHostname desHostname [type [state]]
|
||||||
|
// type = a valid request type
|
||||||
|
// state = [`block`, `allow`, `inherit`]
|
||||||
|
|
||||||
|
// srcHostname desHostname type
|
||||||
|
// type = a valid request type
|
||||||
|
// state = `allow`
|
||||||
|
|
||||||
|
// srcHostname desHostname
|
||||||
|
// type = `*`
|
||||||
|
// state = `allow`
|
||||||
|
|
||||||
|
// Lines with invalid syntax silently ignored
|
||||||
|
|
||||||
|
srcHostname = punycode.toASCII(fields[0]);
|
||||||
|
desHostname = punycode.toASCII(fields[1]);
|
||||||
|
|
||||||
|
fieldVal = fields[2];
|
||||||
|
|
||||||
|
if ( fieldVal !== undefined ) {
|
||||||
|
type = fieldVal;
|
||||||
|
// Unknown type: reject
|
||||||
|
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type = '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldVal = fields[3];
|
||||||
|
|
||||||
|
if ( fieldVal !== undefined ) {
|
||||||
|
// Unknown state: reject
|
||||||
|
if ( nameToStateMap.hasOwnProperty(fieldVal) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
state = nameToStateMap[fieldVal];
|
||||||
|
} else {
|
||||||
|
state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setCell(srcHostname, desHostname, type, state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.fromObsoleteSelfie = function(selfie) {
|
||||||
|
if ( selfie === '' ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
var bin = JSON.parse(selfie);
|
||||||
|
var filters = bin.filters;
|
||||||
|
var bits, val;
|
||||||
|
for ( var hostname in filters ) {
|
||||||
|
if ( filters.hasOwnProperty(hostname) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bits = filters[hostname];
|
||||||
|
val = bits & 3;
|
||||||
|
if ( val === 1 ) {
|
||||||
|
this.setCell(hostname, '*', 'inline-script', 1);
|
||||||
|
} else if ( val === 2 ) {
|
||||||
|
this.setCell(hostname, '*', 'inline-script', 3);
|
||||||
|
}
|
||||||
|
val = (bits >> 2) & 3;
|
||||||
|
if ( val === 1 ) {
|
||||||
|
this.setCell(hostname, '*', '1p-script', 1);
|
||||||
|
} else if ( val === 2 ) {
|
||||||
|
this.setCell(hostname, '*', '1p-script', 3);
|
||||||
|
}
|
||||||
|
val = (bits >> 4) & 3;
|
||||||
|
if ( val === 1 ) {
|
||||||
|
this.setCell(hostname, '*', '3p-script', 1);
|
||||||
|
} else if ( val === 2 ) {
|
||||||
|
this.setCell(hostname, '*', '3p-script', 3);
|
||||||
|
}
|
||||||
|
val = (bits >> 8) & 3;
|
||||||
|
if ( val === 1 ) {
|
||||||
|
this.setCell(hostname, '*', '3p-frame', 1);
|
||||||
|
} else if ( val === 2 ) {
|
||||||
|
this.setCell(hostname, '*', '3p-frame', 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.toSelfie = function() {
|
||||||
|
return {
|
||||||
|
magicId: magicId,
|
||||||
|
rules: this.rules
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.fromSelfie = function(selfie) {
|
||||||
|
this.rules = selfie.rules;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
return new Matrix;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// http://youtu.be/5-K8R1hDG9E?t=31m1s
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
@ -42,10 +42,6 @@ var onMessage = function(request, sender, callback) {
|
|||||||
µb.assets.get(request.url, callback);
|
µb.assets.get(request.url, callback);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'loadUbiquitousAllowRules':
|
|
||||||
µb.loadUbiquitousWhitelists();
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -108,13 +104,14 @@ var µb = µBlock;
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var getDynamicFilterResults = function(scope) {
|
var getDynamicFilterResults = function(scope) {
|
||||||
return [
|
var r = {};
|
||||||
µb.netFilteringEngine.matchDynamicFilters(scope, 'inline-script', true),
|
var dFiltering = µb.dynamicNetFilteringEngine;
|
||||||
µb.netFilteringEngine.matchDynamicFilters(scope, 'script', true),
|
r['image'] = dFiltering.evaluateCellZY(scope, '*', 'image').toFilterString();
|
||||||
µb.netFilteringEngine.matchDynamicFilters(scope, 'script', false),
|
r['inline-script'] = dFiltering.evaluateCellZY(scope, '*', 'inline-script').toFilterString();
|
||||||
µb.netFilteringEngine.matchDynamicFilters(scope, 'sub_frame', true),
|
r['1p-script'] = dFiltering.evaluateCellZY(scope, '*', '1p-script').toFilterString();
|
||||||
µb.netFilteringEngine.matchDynamicFilters(scope, 'sub_frame', false)
|
r['3p-script'] = dFiltering.evaluateCellZY(scope, '*', '3p-script').toFilterString();
|
||||||
];
|
r['3p-frame'] = dFiltering.evaluateCellZY(scope, '*', '3p-frame').toFilterString();
|
||||||
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -134,7 +131,7 @@ var getStats = function(tab) {
|
|||||||
logRequests: µb.userSettings.logRequests,
|
logRequests: µb.userSettings.logRequests,
|
||||||
dynamicFilteringEnabled: µb.userSettings.dynamicFilteringEnabled,
|
dynamicFilteringEnabled: µb.userSettings.dynamicFilteringEnabled,
|
||||||
dynamicFilterResults: {
|
dynamicFilterResults: {
|
||||||
'/': getDynamicFilterResults('*')
|
'*': getDynamicFilterResults('*')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var pageStore = tab && µb.pageStoreFromTabId(tab.id);
|
var pageStore = tab && µb.pageStoreFromTabId(tab.id);
|
||||||
@ -145,7 +142,7 @@ var getStats = function(tab) {
|
|||||||
r.pageBlockedRequestCount = pageStore.perLoadBlockedRequestCount;
|
r.pageBlockedRequestCount = pageStore.perLoadBlockedRequestCount;
|
||||||
r.pageAllowedRequestCount = pageStore.perLoadAllowedRequestCount;
|
r.pageAllowedRequestCount = pageStore.perLoadAllowedRequestCount;
|
||||||
r.netFilteringSwitch = pageStore.getNetFilteringSwitch();
|
r.netFilteringSwitch = pageStore.getNetFilteringSwitch();
|
||||||
r.dynamicFilterResults['.'] = getDynamicFilterResults(r.pageHostname);
|
r.dynamicFilterResults['local'] = getDynamicFilterResults(r.pageHostname);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
@ -185,9 +182,9 @@ var onMessage = function(request, sender, callback) {
|
|||||||
|
|
||||||
case 'toggleDynamicFilter':
|
case 'toggleDynamicFilter':
|
||||||
µb.toggleDynamicFilter(request);
|
µb.toggleDynamicFilter(request);
|
||||||
response = { '/': getDynamicFilterResults('*') };
|
response = { '*': getDynamicFilterResults('*') };
|
||||||
if ( request.pageHostname ) {
|
if ( request.pageHostname ) {
|
||||||
response['.'] = getDynamicFilterResults(request.pageHostname);
|
response['local'] = getDynamicFilterResults(request.pageHostname);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -281,9 +278,13 @@ var tagNameToRequestTypeMap = {
|
|||||||
// Evaluate many requests
|
// Evaluate many requests
|
||||||
|
|
||||||
var filterRequests = function(pageStore, details) {
|
var filterRequests = function(pageStore, details) {
|
||||||
details.pageDomain = µb.URI.domainFromHostname(details.pageHostname);
|
var µburi = µb.URI;
|
||||||
|
|
||||||
|
// Create evaluation context
|
||||||
|
details.pageDomain = µburi.domainFromHostname(details.pageHostname);
|
||||||
details.rootHostname = pageStore.rootHostname;
|
details.rootHostname = pageStore.rootHostname;
|
||||||
details.rootDomain = pageStore.rootDomain;
|
details.rootDomain = pageStore.rootDomain;
|
||||||
|
details.requestHostname = '';
|
||||||
|
|
||||||
var inRequests = details.requests;
|
var inRequests = details.requests;
|
||||||
var outRequests = [];
|
var outRequests = [];
|
||||||
@ -294,11 +295,10 @@ var filterRequests = function(pageStore, details) {
|
|||||||
if ( tagNameToRequestTypeMap.hasOwnProperty(request.tagName) === false ) {
|
if ( tagNameToRequestTypeMap.hasOwnProperty(request.tagName) === false ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result = pageStore.filterRequest(
|
details.requestURL = request.url;
|
||||||
details,
|
details.requestHostname = µburi.hostnameFromURI(request.url);
|
||||||
tagNameToRequestTypeMap[request.tagName],
|
details.requestType = tagNameToRequestTypeMap[request.tagName];
|
||||||
request.url
|
result = pageStore.filterRequest(details);
|
||||||
);
|
|
||||||
if ( pageStore.boolFromResult(result) ) {
|
if ( pageStore.boolFromResult(result) ) {
|
||||||
outRequests.push(request);
|
outRequests.push(request);
|
||||||
}
|
}
|
||||||
@ -317,14 +317,13 @@ var filterRequest = function(pageStore, details) {
|
|||||||
if ( tagNameToRequestTypeMap.hasOwnProperty(details.tagName) === false ) {
|
if ( tagNameToRequestTypeMap.hasOwnProperty(details.tagName) === false ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
details.pageDomain = µb.URI.domainFromHostname(details.pageHostname);
|
var µburi = µb.URI;
|
||||||
|
details.pageDomain = µburi.domainFromHostname(details.pageHostname);
|
||||||
details.rootHostname = pageStore.rootHostname;
|
details.rootHostname = pageStore.rootHostname;
|
||||||
details.rootDomain = pageStore.rootDomain;
|
details.rootDomain = pageStore.rootDomain;
|
||||||
var result = pageStore.filterRequest(
|
details.requestHostname = µburi.hostnameFromURI(details.requestURL);
|
||||||
details,
|
details.requestType = tagNameToRequestTypeMap[details.tagName];
|
||||||
tagNameToRequestTypeMap[details.tagName],
|
var result = pageStore.filterRequest(details);
|
||||||
details.requestURL
|
|
||||||
);
|
|
||||||
if ( pageStore.boolFromResult(result) ) {
|
if ( pageStore.boolFromResult(result) ) {
|
||||||
return { collapse: µb.userSettings.collapseBlocked };
|
return { collapse: µb.userSettings.collapseBlocked };
|
||||||
}
|
}
|
||||||
@ -485,7 +484,7 @@ var getLists = function(callback) {
|
|||||||
available: null,
|
available: null,
|
||||||
current: µb.remoteBlacklists,
|
current: µb.remoteBlacklists,
|
||||||
cosmetic: µb.userSettings.parseAllABPHideFilters,
|
cosmetic: µb.userSettings.parseAllABPHideFilters,
|
||||||
netFilterCount: µb.netFilteringEngine.getFilterCount(),
|
netFilterCount: µb.staticNetFilteringEngine.getFilterCount(),
|
||||||
cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(),
|
cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(),
|
||||||
autoUpdate: µb.userSettings.autoUpdate,
|
autoUpdate: µb.userSettings.autoUpdate,
|
||||||
userFiltersPath: µb.userFiltersPath,
|
userFiltersPath: µb.userFiltersPath,
|
||||||
|
@ -245,6 +245,9 @@ FrameStore.prototype.init = function(rootHostname, frameURL) {
|
|||||||
this.pageDomain = µburi.domainFromHostname(this.pageHostname) || this.pageHostname;
|
this.pageDomain = µburi.domainFromHostname(this.pageHostname) || this.pageHostname;
|
||||||
this.rootHostname = rootHostname;
|
this.rootHostname = rootHostname;
|
||||||
this.rootDomain = µburi.domainFromHostname(rootHostname) || rootHostname;
|
this.rootDomain = µburi.domainFromHostname(rootHostname) || rootHostname;
|
||||||
|
// This is part of the filtering evaluation context
|
||||||
|
this.requestURL = this.requestHostname = this.requestType = '';
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,7 +255,8 @@ FrameStore.prototype.init = function(rootHostname, frameURL) {
|
|||||||
|
|
||||||
FrameStore.prototype.dispose = function() {
|
FrameStore.prototype.dispose = function() {
|
||||||
this.pageHostname = this.pageDomain =
|
this.pageHostname = this.pageDomain =
|
||||||
this.rootHostname = this.rootDomain = '';
|
this.rootHostname = this.rootDomain =
|
||||||
|
this.requestURL = this.requestHostname = this.requestType = '';
|
||||||
if ( frameStoreJunkyard.length < frameStoreJunkyardMax ) {
|
if ( frameStoreJunkyard.length < frameStoreJunkyardMax ) {
|
||||||
frameStoreJunkyard.push(this);
|
frameStoreJunkyard.push(this);
|
||||||
}
|
}
|
||||||
@ -292,6 +296,16 @@ PageStore.factory = function(tabId, pageURL) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
PageStore.prototype.bitFromRequestType = {
|
||||||
|
'': 1,
|
||||||
|
'sb': 2,
|
||||||
|
'sa': 4,
|
||||||
|
'db': 8,
|
||||||
|
'da': 16
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
PageStore.prototype.init = function(tabId, pageURL) {
|
PageStore.prototype.init = function(tabId, pageURL) {
|
||||||
this.tabId = tabId;
|
this.tabId = tabId;
|
||||||
this.previousPageURL = '';
|
this.previousPageURL = '';
|
||||||
@ -304,6 +318,10 @@ PageStore.prototype.init = function(tabId, pageURL) {
|
|||||||
this.rootHostname = this.pageHostname;
|
this.rootHostname = this.pageHostname;
|
||||||
this.rootDomain = this.pageDomain;
|
this.rootDomain = this.pageDomain;
|
||||||
|
|
||||||
|
// This is part of the filtering evaluation context
|
||||||
|
this.requestURL = this.requestHostname = this.requestType = '';
|
||||||
|
this.requestHostnames = {};
|
||||||
|
|
||||||
this.frames = {};
|
this.frames = {};
|
||||||
this.netFiltering = true;
|
this.netFiltering = true;
|
||||||
this.netFilteringReadTime = 0;
|
this.netFilteringReadTime = 0;
|
||||||
@ -361,7 +379,9 @@ PageStore.prototype.dispose = function() {
|
|||||||
// used as a key).
|
// used as a key).
|
||||||
this.pageURL = this.previousPageURL =
|
this.pageURL = this.previousPageURL =
|
||||||
this.pageHostname = this.pageDomain =
|
this.pageHostname = this.pageDomain =
|
||||||
this.rootHostname = this.rootDomain = '';
|
this.rootHostname = this.rootDomain =
|
||||||
|
this.requestURL = this.requestHostname = this.requestType = '';
|
||||||
|
this.requestHostnames = null;
|
||||||
this.disposeFrameStores();
|
this.disposeFrameStores();
|
||||||
this.netFilteringCache = this.netFilteringCache.dispose();
|
this.netFilteringCache = this.netFilteringCache.dispose();
|
||||||
if ( pageStoreJunkyard.length < pageStoreJunkyardMax ) {
|
if ( pageStoreJunkyard.length < pageStoreJunkyardMax ) {
|
||||||
@ -374,11 +394,8 @@ PageStore.prototype.dispose = function() {
|
|||||||
|
|
||||||
PageStore.prototype.disposeFrameStores = function() {
|
PageStore.prototype.disposeFrameStores = function() {
|
||||||
var frames = this.frames;
|
var frames = this.frames;
|
||||||
if ( typeof frames === 'object' ) {
|
for ( var k in frames ) {
|
||||||
for ( var k in frames ) {
|
if ( frames.hasOwnProperty(k) ) {
|
||||||
if ( frames.hasOwnProperty(k) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
frames[k].dispose();
|
frames[k].dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,20 +431,32 @@ PageStore.prototype.getNetFilteringSwitch = function() {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
PageStore.prototype.filterRequest = function(context, requestType, requestURL) {
|
PageStore.prototype.filterRequest = function(context) {
|
||||||
var result = '';
|
var requestURL = context.requestURL;
|
||||||
if ( this.getNetFilteringSwitch() ) {
|
|
||||||
var entry = this.netFilteringCache.lookup(requestURL);
|
if ( this.getNetFilteringSwitch() === false ) {
|
||||||
if ( entry !== undefined ) {
|
this.recordResult(context.requestType, requestURL, '');
|
||||||
//console.debug(' cache HIT: PageStore.filterRequest("%s")', requestURL);
|
return '';
|
||||||
return entry.result;
|
|
||||||
}
|
|
||||||
//console.debug('cache MISS: PageStore.filterRequest("%s")', requestURL);
|
|
||||||
result = µb.netFilteringEngine.matchString(context, requestURL, requestType);
|
|
||||||
}
|
}
|
||||||
if ( collapsibleRequestTypes.indexOf(requestType) !== -1 || µb.userSettings.logRequests ) {
|
|
||||||
this.netFilteringCache.add(requestURL, result, requestType, 0);
|
var entry = this.netFilteringCache.lookup(requestURL);
|
||||||
|
if ( entry !== undefined ) {
|
||||||
|
//console.debug('cache HIT: PageStore.filterRequest("%s")', requestURL);
|
||||||
|
return entry.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var result = µb.filterRequest(context);
|
||||||
|
|
||||||
|
//console.debug('cache MISS: PageStore.filterRequest("%s")', requestURL);
|
||||||
|
this.recordResult(context.requestType, requestURL, result);
|
||||||
|
|
||||||
|
var requestHostname = context.requestHostname;
|
||||||
|
if ( this.requestHostnames.hasOwnProperty(requestHostname) ) {
|
||||||
|
this.requestHostnames[requestHostname] |= this.bitFromRequestType[result.slice(0, 2)];
|
||||||
|
} else {
|
||||||
|
this.requestHostnames[requestHostname] = this.bitFromRequestType[result.slice(0, 2)];
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -454,7 +483,7 @@ PageStore.prototype.recordResult = function(requestType, requestURL, result) {
|
|||||||
// true: blocked
|
// true: blocked
|
||||||
|
|
||||||
PageStore.prototype.boolFromResult = function(result) {
|
PageStore.prototype.boolFromResult = function(result) {
|
||||||
return typeof result === 'string' && result !== '' && result.slice(0, 2) !== '@@';
|
return typeof result === 'string' && result.charAt(1) === 'b';
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var stats;
|
var stats;
|
||||||
var reResultParser = /^(@@)?(\*|\|\|([^$^]+)\^)\$(.+)$/;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@ -50,23 +49,23 @@ var formatNumber = function(count) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var syncDynamicFilter = function(scope, i, result) {
|
var syncDynamicFilter = function(scope, des, type, result) {
|
||||||
var el = uDom('[data-scope="' + scope + '"] > div:nth-of-type(' + i + ')');
|
var el = uDom('span[data-src="' + scope + '"][data-des="' + des + '"][data-type="' + type + '"]');
|
||||||
var matches = reResultParser.exec(result) || [];
|
var blocked = result.charAt(1) === 'b';
|
||||||
var blocked = matches.length !== 0 && matches[1] !== '@@';
|
|
||||||
el.toggleClass('blocked', blocked);
|
el.toggleClass('blocked', blocked);
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/340
|
// https://github.com/gorhill/uBlock/issues/340
|
||||||
// Use dark shade visual cue if the filter is specific to the page hostname
|
// Use dark shade visual cue if the filter is specific to the page hostname
|
||||||
// or one of the ancestor hostname.
|
// or one of the ancestor hostname.
|
||||||
var ownFilter = false;
|
var ownFilter = false;
|
||||||
// There might be no page hostname on pages where uBlock can't be active,
|
var matches = /^d[abn]:([^ ]+)/.exec(result);
|
||||||
// like on browser's built-in pages, etc.
|
if ( matches !== null ) {
|
||||||
if ( stats.pageHostname ) {
|
var thisSrc = scope === 'local' ? stats.pageHostname : '*';
|
||||||
var filterHostname = matches[3] || '*';
|
var otherSrc = matches[1];
|
||||||
if ( stats.pageHostname.slice(0 - filterHostname.length) === filterHostname ) {
|
ownFilter = thisSrc.slice(0 - otherSrc.length) === thisSrc;
|
||||||
ownFilter = (stats.pageHostname.length === filterHostname.length) ||
|
if ( ownFilter && thisSrc.length !== otherSrc.length ) {
|
||||||
(stats.pageHostname.substr(0 - filterHostname.length - 1, 1) === '.');
|
var c = thisSrc.substr(0 - otherSrc.length - 1, 1);
|
||||||
|
ownFilter = c === '' || c === '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
el.toggleClass('ownFilter', ownFilter);
|
el.toggleClass('ownFilter', ownFilter);
|
||||||
@ -76,23 +75,25 @@ var syncDynamicFilter = function(scope, i, result) {
|
|||||||
|
|
||||||
var syncAllDynamicFilters = function() {
|
var syncAllDynamicFilters = function() {
|
||||||
var hasBlock = false;
|
var hasBlock = false;
|
||||||
var scopes = ['.', '/'];
|
var scopes = ['*', 'local'];
|
||||||
var scope, results, i, result;
|
var scope, results, i, result;
|
||||||
while ( scope = scopes.pop() ) {
|
while ( scope = scopes.pop() ) {
|
||||||
if ( stats.dynamicFilterResults.hasOwnProperty(scope) === false ) {
|
if ( stats.dynamicFilterResults.hasOwnProperty(scope) === false ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
results = stats.dynamicFilterResults[scope];
|
results = stats.dynamicFilterResults[scope];
|
||||||
i = 5;
|
for ( var type in results ) {
|
||||||
while ( i-- ) {
|
if ( results.hasOwnProperty(type) === false ) {
|
||||||
result = results[i];
|
continue;
|
||||||
syncDynamicFilter(scope, i + 1, result);
|
}
|
||||||
if ( scope === '.' && result.length !== 0 && result.slice(0, 2) !== '@@' ) {
|
result = results[type];
|
||||||
|
syncDynamicFilter(scope, '*', type, result);
|
||||||
|
if ( scope === 'local' && result.charAt(1) === 'b' ) {
|
||||||
hasBlock = true;
|
hasBlock = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uDom('#dynamicFilteringToggler').toggleClass('hasBlock', hasBlock);
|
uDom('body').toggleClass('hasDynamicBlock', hasBlock);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -165,7 +166,7 @@ var renderPopup = function(details) {
|
|||||||
|
|
||||||
uDom('#total-blocked').html(html.join(''));
|
uDom('#total-blocked').html(html.join(''));
|
||||||
uDom('#switch .fa').toggleClass('off', stats.pageURL === '' || !stats.netFilteringSwitch);
|
uDom('#switch .fa').toggleClass('off', stats.pageURL === '' || !stats.netFilteringSwitch);
|
||||||
uDom('#dynamicFilteringToggler').toggleClass('on', stats.dynamicFilteringEnabled);
|
uDom('body').toggleClass('dynamicFilteringEnabled', stats.dynamicFilteringEnabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -174,12 +175,11 @@ var toggleNetFilteringSwitch = function(ev) {
|
|||||||
if ( !stats || !stats.pageURL ) {
|
if ( !stats || !stats.pageURL ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var off = uDom(this).toggleClass('off').hasClassName('off');
|
|
||||||
messager.send({
|
messager.send({
|
||||||
what: 'toggleNetFiltering',
|
what: 'toggleNetFiltering',
|
||||||
url: stats.pageURL,
|
url: stats.pageURL,
|
||||||
scope: ev.ctrlKey || ev.metaKey ? 'page' : '',
|
scope: ev.ctrlKey || ev.metaKey ? 'page' : '',
|
||||||
state: !off,
|
state: !uDom(this).toggleClass('off').hasClass('off'),
|
||||||
tabId: stats.tabId
|
tabId: stats.tabId
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -242,37 +242,35 @@ var gotoLink = function(ev) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var onDynamicFilterClicked = function(ev) {
|
var onDynamicFilterClicked = function(ev) {
|
||||||
var elScope = uDom(ev.currentTarget);
|
// This can happen on pages where uBlock does not work
|
||||||
var scope = elScope.attr('data-scope') === '/' ? '*' : stats.pageHostname;
|
if ( typeof stats.pageHostname !== 'string' || stats.pageHostname === '' ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var elFilter = uDom(ev.target);
|
var elFilter = uDom(ev.target);
|
||||||
|
var scope = elFilter.attr('data-src') === '*' ? '*' : stats.pageHostname;
|
||||||
var onDynamicFilterChanged = function(details) {
|
var onDynamicFilterChanged = function(details) {
|
||||||
stats.dynamicFilterResults = details;
|
stats.dynamicFilterResults = details;
|
||||||
syncAllDynamicFilters();
|
syncAllDynamicFilters();
|
||||||
};
|
};
|
||||||
messager.send({
|
messager.send({
|
||||||
what: 'toggleDynamicFilter',
|
what: 'toggleDynamicFilter',
|
||||||
hostname: scope,
|
pageHostname: stats.pageHostname,
|
||||||
|
srcHostname: scope,
|
||||||
|
desHostname: elFilter.attr('data-des'),
|
||||||
requestType: elFilter.attr('data-type'),
|
requestType: elFilter.attr('data-type'),
|
||||||
firstParty: elFilter.attr('data-first-party') !== null,
|
block: elFilter.hasClassName('blocked') === false
|
||||||
block: elFilter.hasClassName('blocked') === false,
|
|
||||||
pageHostname: stats.pageHostname
|
|
||||||
}, onDynamicFilterChanged);
|
}, onDynamicFilterChanged);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var toggleDynamicFiltering = function(ev) {
|
var toggleDynamicFiltering = function(ev) {
|
||||||
// Discard events destined to child elements.
|
var el = uDom('body');
|
||||||
if ( ev !== undefined && ev.target !== this ) {
|
el.toggleClass('dynamicFilteringEnabled');
|
||||||
return;
|
|
||||||
}
|
|
||||||
var el = uDom('#dynamicFilteringToggler');
|
|
||||||
el.toggleClass('on');
|
|
||||||
messager.send({
|
messager.send({
|
||||||
what: 'userSettings',
|
what: 'userSettings',
|
||||||
name: 'dynamicFilteringEnabled',
|
name: 'dynamicFilteringEnabled',
|
||||||
value: el.hasClassName('on')
|
value: el.hasClassName('dynamicFilteringEnabled')
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -285,7 +283,7 @@ var installEventHandlers = function() {
|
|||||||
uDom('#gotoPick').on('click', gotoPick);
|
uDom('#gotoPick').on('click', gotoPick);
|
||||||
uDom('a[href^=http]').on('click', gotoLink);
|
uDom('a[href^=http]').on('click', gotoLink);
|
||||||
uDom('#dynamicFilteringToggler').on('click', toggleDynamicFiltering);
|
uDom('#dynamicFilteringToggler').on('click', toggleDynamicFiltering);
|
||||||
uDom('.dynamicFiltering').on('click', 'div', onDynamicFilterClicked);
|
uDom('#dynamicFilteringContainer').on('click', 'span[data-type]', onDynamicFilterClicked);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* jshint bitwise: false */
|
/* jshint bitwise: false, esnext: true */
|
||||||
/* global µBlock */
|
/* global µBlock */
|
||||||
|
|
||||||
// Older Safari throws an exception for const when it's used with 'use strict'.
|
// Older Safari throws an exception for const when it's used with 'use strict'.
|
||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.netFilteringEngine = (function(){
|
µBlock.staticNetFilteringEngine = (function(){
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@ -1284,7 +1284,6 @@ var FilterContainer = function() {
|
|||||||
this.buckets = new Array(4);
|
this.buckets = new Array(4);
|
||||||
this.blockedAnyPartyHostnames = new µb.LiquidDict();
|
this.blockedAnyPartyHostnames = new µb.LiquidDict();
|
||||||
this.blocked3rdPartyHostnames = new µb.LiquidDict();
|
this.blocked3rdPartyHostnames = new µb.LiquidDict();
|
||||||
this.dynamicFilters = {};
|
|
||||||
this.filterParser = new FilterParser();
|
this.filterParser = new FilterParser();
|
||||||
this.reset();
|
this.reset();
|
||||||
};
|
};
|
||||||
@ -1642,193 +1641,6 @@ FilterContainer.prototype.addToCategory = function(category, tokenKey, filter) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Dynamic filters
|
|
||||||
|
|
||||||
// Bits:
|
|
||||||
// 0: inline script blocked
|
|
||||||
// 1: inline script allowed
|
|
||||||
// 2: first-party script blocked
|
|
||||||
// 3: first-party script allowed
|
|
||||||
// 4: third-party script blocked
|
|
||||||
// 5: third-party script allowed
|
|
||||||
// 6: first-party frame blocked
|
|
||||||
// 7: first-party frame allowed
|
|
||||||
// 8: third-party frame blocked
|
|
||||||
// 9: third-party frame allowed
|
|
||||||
//
|
|
||||||
// I chose separate bits for blocked/unblocked as I want to have an "undefined"
|
|
||||||
// state, which will be used to inherit from wider-scoped filters.
|
|
||||||
//
|
|
||||||
// undefined: 0x00
|
|
||||||
// blocked: 0x01
|
|
||||||
// allowed: 0x02
|
|
||||||
// unused: 0x03
|
|
||||||
|
|
||||||
FilterContainer.prototype.dynamicFilterBitOffsets = {};
|
|
||||||
FilterContainer.prototype.dynamicFilterBitOffsets[FirstParty | typeNameToTypeValue['inline-script']] = 0;
|
|
||||||
FilterContainer.prototype.dynamicFilterBitOffsets[FirstParty | typeNameToTypeValue.script] = 2;
|
|
||||||
FilterContainer.prototype.dynamicFilterBitOffsets[ThirdParty | typeNameToTypeValue.script] = 4;
|
|
||||||
FilterContainer.prototype.dynamicFilterBitOffsets[FirstParty | typeNameToTypeValue.sub_frame] = 6;
|
|
||||||
FilterContainer.prototype.dynamicFilterBitOffsets[ThirdParty | typeNameToTypeValue.sub_frame] = 8;
|
|
||||||
FilterContainer.prototype.dynamicFiltersMagicId = 'numrebvoacir';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
FilterContainer.prototype.dynamicFilterSet = function(hostname, requestType, firstParty, value) {
|
|
||||||
if ( typeNameToTypeValue.hasOwnProperty(requestType) === false ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var party = firstParty ? FirstParty : ThirdParty;
|
|
||||||
var categoryKey = party | typeNameToTypeValue[requestType];
|
|
||||||
if ( this.dynamicFilterBitOffsets.hasOwnProperty(categoryKey) === false ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var bitOffset = this.dynamicFilterBitOffsets[categoryKey];
|
|
||||||
var oldFilter = this.dynamicFilters[hostname] || 0;
|
|
||||||
var newFilter = (oldFilter & ~(0x0003 << bitOffset)) | (value << bitOffset);
|
|
||||||
if ( newFilter === oldFilter ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( newFilter === 0 ) {
|
|
||||||
delete this.dynamicFilters[hostname];
|
|
||||||
} else {
|
|
||||||
this.dynamicFilters[hostname] = newFilter;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
FilterContainer.prototype.dynamicFilterBlock = function(hostname, requestType, firstParty) {
|
|
||||||
if ( typeof hostname !== 'string' || hostname === '' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var result = this.matchDynamicFilters(hostname, requestType, firstParty);
|
|
||||||
if ( result !== '' && result.slice(0, 2) !== '@@' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.dynamicFilterSet(hostname, requestType, firstParty, 0x00);
|
|
||||||
result = this.matchDynamicFilters(hostname, requestType, firstParty);
|
|
||||||
if ( result !== '' && result.slice(0, 2) !== '@@' ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this.dynamicFilterSet(hostname, requestType, firstParty, 0x01);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
FilterContainer.prototype.dynamicFilterUnblock = function(hostname, requestType, firstParty) {
|
|
||||||
if ( typeof hostname !== 'string' || hostname === '' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var result = this.matchDynamicFilters(hostname, requestType, firstParty);
|
|
||||||
if ( result === '' || result.slice(0, 2) === '@@' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.dynamicFilterSet(hostname, requestType, firstParty, 0x00);
|
|
||||||
result = this.matchDynamicFilters(hostname, requestType, firstParty);
|
|
||||||
if ( result === '' || result.slice(0, 2) === '@@' ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this.dynamicFilterSet(hostname, requestType, firstParty, 0x02);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
FilterContainer.prototype.dynamicFilterStateToType = {
|
|
||||||
0x0001: '',
|
|
||||||
0x0002: '@@',
|
|
||||||
0x0004: '',
|
|
||||||
0x0008: '@@',
|
|
||||||
0x0010: '',
|
|
||||||
0x0020: '@@',
|
|
||||||
0x0040: '',
|
|
||||||
0x0080: '@@',
|
|
||||||
0x0100: '',
|
|
||||||
0x0200: '@@'
|
|
||||||
};
|
|
||||||
|
|
||||||
FilterContainer.prototype.dynamicFilterStateToOption = {
|
|
||||||
0x0001: '$inline-script,important',
|
|
||||||
0x0002: '$inline-script',
|
|
||||||
0x0004: '$~third-party,script,important',
|
|
||||||
0x0008: '$~third-party,script',
|
|
||||||
0x0010: '$third-party,script,important',
|
|
||||||
0x0020: '$third-party,script',
|
|
||||||
0x0040: '$~third-party,subdocument,important',
|
|
||||||
0x0080: '$~third-party,subdocument',
|
|
||||||
0x0100: '$third-party,subdocument,important',
|
|
||||||
0x0200: '$third-party,subdocument'
|
|
||||||
};
|
|
||||||
|
|
||||||
FilterContainer.prototype.matchDynamicFilters = function(hostname, requestType, firstParty) {
|
|
||||||
if ( typeof hostname !== 'string' || hostname === '' ) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
var party = firstParty ? FirstParty : ThirdParty;
|
|
||||||
if ( typeNameToTypeValue.hasOwnProperty(requestType) === false ) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
var categoryKey = party | typeNameToTypeValue[requestType];
|
|
||||||
if ( this.dynamicFilterBitOffsets.hasOwnProperty(categoryKey) === false ) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
var bitOffset = this.dynamicFilterBitOffsets[categoryKey];
|
|
||||||
var bitMask = 0x0003 << bitOffset;
|
|
||||||
var bitState, pos;
|
|
||||||
for ( ;; ) {
|
|
||||||
if ( this.dynamicFilters.hasOwnProperty(hostname) !== false ) {
|
|
||||||
bitState = this.dynamicFilters[hostname] & bitMask;
|
|
||||||
if ( bitState !== 0 ) {
|
|
||||||
if ( hostname !== '*' ) {
|
|
||||||
hostname = '||' + hostname + '^';
|
|
||||||
}
|
|
||||||
return this.dynamicFilterStateToType[bitState] +
|
|
||||||
hostname +
|
|
||||||
this.dynamicFilterStateToOption[bitState];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos = hostname.indexOf('.');
|
|
||||||
if ( pos === -1 ) {
|
|
||||||
if ( hostname === '*' ) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
hostname = '*';
|
|
||||||
} else {
|
|
||||||
hostname = hostname.slice(pos + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// unreachable
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
FilterContainer.prototype.selfieFromDynamicFilters = function() {
|
|
||||||
var bin = {
|
|
||||||
magicId: this.dynamicFiltersMagicId,
|
|
||||||
filters: this.dynamicFilters
|
|
||||||
};
|
|
||||||
return JSON.stringify(bin);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
FilterContainer.prototype.dynamicFiltersFromSelfie = function(selfie) {
|
|
||||||
if ( selfie === '' ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var bin = JSON.parse(selfie);
|
|
||||||
if ( bin.magicId !== this.dynamicFiltersMagicId ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.dynamicFilters = bin.filters;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Since the addition of the `important` evaluation, this means it is now
|
// Since the addition of the `important` evaluation, this means it is now
|
||||||
// likely that the url will have to be scanned more than once. So this is
|
// likely that the url will have to be scanned more than once. So this is
|
||||||
// to ensure we do it once only, and reuse results.
|
// to ensure we do it once only, and reuse results.
|
||||||
@ -1858,15 +1670,9 @@ FilterContainer.prototype.tokenize = function(url) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.matchTokens = function(url) {
|
FilterContainer.prototype.matchTokens = function(bucket, url) {
|
||||||
var buckets = this.buckets;
|
|
||||||
var bucket0 = buckets[0];
|
|
||||||
var bucket1 = buckets[1];
|
|
||||||
var bucket2 = buckets[2];
|
|
||||||
var bucket3 = buckets[3];
|
|
||||||
|
|
||||||
var tokens = this.tokens;
|
var tokens = this.tokens;
|
||||||
var tokenEntry, beg, token, f;
|
var tokenEntry, token, f;
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
tokenEntry = tokens[i++];
|
tokenEntry = tokens[i++];
|
||||||
@ -1874,30 +1680,9 @@ FilterContainer.prototype.matchTokens = function(url) {
|
|||||||
if ( token === '' ) {
|
if ( token === '' ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
beg = tokenEntry.beg;
|
f = bucket[token];
|
||||||
if ( bucket0 !== undefined ) {
|
if ( f !== undefined && f.match(url, tokenEntry.beg) !== false ) {
|
||||||
f = bucket0[token];
|
return f;
|
||||||
if ( f !== undefined && f.match(url, beg) !== false ) {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bucket1 !== undefined ) {
|
|
||||||
f = bucket1[token];
|
|
||||||
if ( f !== undefined && f.match(url, beg) !== false ) {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bucket2 !== undefined ) {
|
|
||||||
f = bucket2[token];
|
|
||||||
if ( f !== undefined && f.match(url, beg) !== false ) {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bucket3 !== undefined ) {
|
|
||||||
f = bucket3[token];
|
|
||||||
if ( f !== undefined && f.match(url, beg) !== false ) {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1955,73 +1740,77 @@ FilterContainer.prototype.match3rdPartyHostname = function(requestHostname) {
|
|||||||
// Some type of requests are exceptional, they need custom handling,
|
// Some type of requests are exceptional, they need custom handling,
|
||||||
// not the generic handling.
|
// not the generic handling.
|
||||||
|
|
||||||
FilterContainer.prototype.matchStringExactType = function(pageDetails, requestURL, requestType) {
|
FilterContainer.prototype.matchStringExactType = function(context, requestURL, requestType) {
|
||||||
var url = requestURL.toLowerCase();
|
var url = requestURL.toLowerCase();
|
||||||
var requestHostname = µb.URI.hostnameFromURI(requestURL);
|
var requestHostname = µb.URI.hostnameFromURI(requestURL);
|
||||||
|
var party = isFirstParty(context.pageDomain, requestHostname) ? FirstParty : ThirdParty;
|
||||||
// Evaluate dynamic filters first. "Block" dynamic filters are always
|
|
||||||
// "important", they override everything else.
|
|
||||||
var bf = this.matchDynamicFilters(
|
|
||||||
pageDetails.rootHostname,
|
|
||||||
requestType,
|
|
||||||
isFirstParty(pageDetails.rootDomain, requestHostname)
|
|
||||||
);
|
|
||||||
if ( bf !== '' && bf.slice(0, 2) !== '@@' ) {
|
|
||||||
return bf;
|
|
||||||
}
|
|
||||||
|
|
||||||
var party = isFirstParty(pageDetails.pageDomain, requestHostname) ? FirstParty : ThirdParty;
|
|
||||||
|
|
||||||
// This will be used by hostname-based filters
|
// This will be used by hostname-based filters
|
||||||
pageHostname = pageDetails.pageHostname || '';
|
pageHostname = context.pageHostname || '';
|
||||||
|
|
||||||
var type = typeNameToTypeValue[requestType];
|
var type = typeNameToTypeValue[requestType];
|
||||||
var categories = this.categories;
|
var categories = this.categories;
|
||||||
var buckets = this.buckets;
|
var bucket;
|
||||||
|
|
||||||
// Tokenize only once
|
// Tokenize only once
|
||||||
this.tokenize(url);
|
this.tokenize(url);
|
||||||
|
|
||||||
// We are testing for a specific type, skip "any type" buckets
|
|
||||||
buckets[0] = buckets[1] = undefined;
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/139
|
// https://github.com/gorhill/uBlock/issues/139
|
||||||
// Test against important block filters
|
// Test against important block filters
|
||||||
buckets[2] = categories[this.makeCategoryKey(BlockAnyParty | Important | type)];
|
if ( bucket = categories[this.makeCategoryKey(BlockAnyParty | Important | type)] ) {
|
||||||
buckets[3] = categories[this.makeCategoryKey(BlockAction | Important | type | party)];
|
bf = this.matchTokens(bucket, url);
|
||||||
bf = this.matchTokens(url);
|
if ( bf !== false ) {
|
||||||
if ( bf !== false ) {
|
return 'sb:' + bf.toString();
|
||||||
return bf.toString();
|
}
|
||||||
|
}
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(BlockAction | Important | type | party)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
if ( bf !== false ) {
|
||||||
|
return 'sb:' + bf.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test against block filters
|
// Test against block filters
|
||||||
|
bf = false;
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(BlockAnyParty | type)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
}
|
||||||
|
if ( bf === false ) {
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(BlockAction | type | party)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
// If there is no block filter, no need to test against allow filters
|
// If there is no block filter, no need to test against allow filters
|
||||||
buckets[2] = categories[this.makeCategoryKey(BlockAnyParty | type)];
|
|
||||||
buckets[3] = categories[this.makeCategoryKey(BlockAction | type | party)];
|
|
||||||
bf = this.matchTokens(url);
|
|
||||||
if ( bf === false ) {
|
if ( bf === false ) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test against allow filters
|
// Test against allow filters
|
||||||
buckets[2] = categories[this.makeCategoryKey(AllowAnyParty | type)];
|
var af;
|
||||||
buckets[3] = categories[this.makeCategoryKey(AllowAction | type | party)];
|
if ( bucket = categories[this.makeCategoryKey(AllowAnyParty | type)] ) {
|
||||||
var af = this.matchTokens(url);
|
af = this.matchTokens(bucket, url);
|
||||||
if ( af !== false ) {
|
if ( af !== false ) {
|
||||||
return '@@' + af.toString();
|
return 'sa:' + af.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(AllowAction | type | party)] ) {
|
||||||
|
af = this.matchTokens(bucket, url);
|
||||||
|
if ( af !== false ) {
|
||||||
|
return 'sa:' + af.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bf.toString();
|
return 'sb:' + bf.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.matchString = function(pageDetails, requestURL, requestType) {
|
FilterContainer.prototype.matchString = function(context) {
|
||||||
// https://github.com/gorhill/httpswitchboard/issues/239
|
// https://github.com/gorhill/httpswitchboard/issues/239
|
||||||
// Convert url to lower case:
|
// Convert url to lower case:
|
||||||
// `match-case` option not supported, but then, I saw only one
|
// `match-case` option not supported, but then, I saw only one
|
||||||
// occurrence of it in all the supported lists (bulgaria list).
|
// occurrence of it in all the supported lists (bulgaria list).
|
||||||
var url = requestURL.toLowerCase();
|
var url = context.requestURL.toLowerCase();
|
||||||
|
|
||||||
// The logic here is simple:
|
// The logic here is simple:
|
||||||
//
|
//
|
||||||
@ -2044,27 +1833,15 @@ FilterContainer.prototype.matchString = function(pageDetails, requestURL, reques
|
|||||||
// filters are tested *only* if there is a (unlikely) hit on a block
|
// filters are tested *only* if there is a (unlikely) hit on a block
|
||||||
// filter.
|
// filter.
|
||||||
|
|
||||||
var requestHostname = µb.URI.hostnameFromURI(requestURL);
|
var requestHostname = context.requestHostname;
|
||||||
|
var party = isFirstParty(context.pageDomain, requestHostname) ? FirstParty : ThirdParty;
|
||||||
// Evaluate dynamic filters first. "Block" dynamic filters are always
|
|
||||||
// "important", they override everything else.
|
|
||||||
var bf = this.matchDynamicFilters(
|
|
||||||
pageDetails.rootHostname,
|
|
||||||
requestType,
|
|
||||||
isFirstParty(pageDetails.rootDomain, requestHostname)
|
|
||||||
);
|
|
||||||
if ( bf !== '' && bf.slice(0, 2) !== '@@' ) {
|
|
||||||
return bf;
|
|
||||||
}
|
|
||||||
|
|
||||||
var party = isFirstParty(pageDetails.pageDomain, requestHostname) ? FirstParty : ThirdParty ;
|
|
||||||
|
|
||||||
// This will be used by hostname-based filters
|
// This will be used by hostname-based filters
|
||||||
pageHostname = pageDetails.pageHostname || '';
|
pageHostname = context.pageHostname || '';
|
||||||
|
|
||||||
var type = typeNameToTypeValue[requestType];
|
var type = typeNameToTypeValue[context.requestType];
|
||||||
var categories = this.categories;
|
var categories = this.categories;
|
||||||
var buckets = this.buckets;
|
var bucket;
|
||||||
|
|
||||||
// Tokenize only once
|
// Tokenize only once
|
||||||
this.tokenize(url);
|
this.tokenize(url);
|
||||||
@ -2074,13 +1851,29 @@ FilterContainer.prototype.matchString = function(pageDetails, requestURL, reques
|
|||||||
// The purpose of the `important` option is to reverse the order of
|
// The purpose of the `important` option is to reverse the order of
|
||||||
// evaluation. Normally, it is "evaluate block then evaluate allow", with
|
// evaluation. Normally, it is "evaluate block then evaluate allow", with
|
||||||
// the `important` property it is "evaluate allow then evaluate block".
|
// the `important` property it is "evaluate allow then evaluate block".
|
||||||
buckets[0] = categories[this.makeCategoryKey(BlockAnyTypeAnyParty | Important)];
|
if ( bucket = categories[this.makeCategoryKey(BlockAnyTypeAnyParty | Important)] ) {
|
||||||
buckets[1] = categories[this.makeCategoryKey(BlockAnyType | Important | party)];
|
bf = this.matchTokens(bucket, url);
|
||||||
buckets[2] = categories[this.makeCategoryKey(BlockAnyParty | Important | type)];
|
if ( bf !== false ) {
|
||||||
buckets[3] = categories[this.makeCategoryKey(BlockAction | Important | type | party)];
|
return 'sb:' + bf.toString() + '$important';
|
||||||
bf = this.matchTokens(url);
|
}
|
||||||
if ( bf !== false ) {
|
}
|
||||||
return bf.toString() + '$important';
|
if ( bucket = categories[this.makeCategoryKey(BlockAnyType | Important | party)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
if ( bf !== false ) {
|
||||||
|
return 'sb:' + bf.toString() + '$important';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(BlockAnyParty | Important | type)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
if ( bf !== false ) {
|
||||||
|
return 'sb:' + bf.toString() + '$important';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(BlockAction | Important | type | party)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
if ( bf !== false ) {
|
||||||
|
return 'sb:' + bf.toString() + '$important';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test hostname-based block filters
|
// Test hostname-based block filters
|
||||||
@ -2091,11 +1884,24 @@ FilterContainer.prototype.matchString = function(pageDetails, requestURL, reques
|
|||||||
|
|
||||||
// Test against block filters
|
// Test against block filters
|
||||||
if ( bf === false ) {
|
if ( bf === false ) {
|
||||||
buckets[0] = categories[this.makeCategoryKey(BlockAnyTypeAnyParty)];
|
if ( bucket = categories[this.makeCategoryKey(BlockAnyTypeAnyParty)] ) {
|
||||||
buckets[1] = categories[this.makeCategoryKey(BlockAnyType | party)];
|
bf = this.matchTokens(bucket, url);
|
||||||
buckets[2] = categories[this.makeCategoryKey(BlockAnyParty | type)];
|
}
|
||||||
buckets[3] = categories[this.makeCategoryKey(BlockAction | type | party)];
|
}
|
||||||
bf = this.matchTokens(url);
|
if ( bf === false ) {
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(BlockAnyType | party)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( bf === false ) {
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(BlockAnyParty | type)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( bf === false ) {
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(BlockAction | type | party)] ) {
|
||||||
|
bf = this.matchTokens(bucket, url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no block filter, no need to test against allow filters
|
// If there is no block filter, no need to test against allow filters
|
||||||
@ -2104,16 +1910,33 @@ FilterContainer.prototype.matchString = function(pageDetails, requestURL, reques
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test against allow filters
|
// Test against allow filters
|
||||||
buckets[0] = categories[this.makeCategoryKey(AllowAnyTypeAnyParty)];
|
var af;
|
||||||
buckets[1] = categories[this.makeCategoryKey(AllowAnyType | party)];
|
if ( bucket = categories[this.makeCategoryKey(AllowAnyTypeAnyParty)] ) {
|
||||||
buckets[2] = categories[this.makeCategoryKey(AllowAnyParty | type)];
|
af = this.matchTokens(bucket, url);
|
||||||
buckets[3] = categories[this.makeCategoryKey(AllowAction | type | party)];
|
if ( af !== false ) {
|
||||||
var af = this.matchTokens(url);
|
return 'sa:' + af.toString();
|
||||||
if ( af !== false ) {
|
}
|
||||||
return '@@' + af.toString();
|
}
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(AllowAnyType | party)] ) {
|
||||||
|
af = this.matchTokens(bucket, url);
|
||||||
|
if ( af !== false ) {
|
||||||
|
return 'sa:' + af.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(AllowAnyParty | type)] ) {
|
||||||
|
af = this.matchTokens(bucket, url);
|
||||||
|
if ( af !== false ) {
|
||||||
|
return 'sa:' + af.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( bucket = categories[this.makeCategoryKey(AllowAction | type | party)] ) {
|
||||||
|
af = this.matchTokens(bucket, url);
|
||||||
|
if ( af !== false ) {
|
||||||
|
return 'sa:' + af.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bf.toString();
|
return 'sb:' + bf.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
@ -21,12 +21,13 @@
|
|||||||
|
|
||||||
/* jshint bitwise: false */
|
/* jshint bitwise: false */
|
||||||
/* global uDom */
|
/* global uDom */
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var messager = vAPI.messaging.channel('stats.js');
|
var messager = vAPI.messaging.channel('stats.js');
|
||||||
@ -77,8 +78,8 @@ var renderURL = function(url, filter) {
|
|||||||
if ( pos > 0 ) {
|
if ( pos > 0 ) {
|
||||||
reText = reText.slice(0, pos);
|
reText = reText.slice(0, pos);
|
||||||
}
|
}
|
||||||
if ( reText.slice(0, 2) === '@@' ) {
|
if ( reText.charAt(0) === 's' ) {
|
||||||
reText = reText.slice(2);
|
reText = reText.slice(3);
|
||||||
}
|
}
|
||||||
if ( reText === '*' ) {
|
if ( reText === '*' ) {
|
||||||
reText = '\\*';
|
reText = '\\*';
|
||||||
|
@ -149,7 +149,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
µb.mergeFilterText(content);
|
µb.mergeFilterText(content);
|
||||||
µb.netFilteringEngine.freeze();
|
µb.staticNetFilteringEngine.freeze();
|
||||||
µb.cosmeticFilteringEngine.freeze();
|
µb.cosmeticFilteringEngine.freeze();
|
||||||
µb.destroySelfie();
|
µb.destroySelfie();
|
||||||
µb.toSelfieAsync();
|
µb.toSelfieAsync();
|
||||||
@ -278,7 +278,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var loadBlacklistsEnd = function() {
|
var loadBlacklistsEnd = function() {
|
||||||
µb.netFilteringEngine.freeze();
|
µb.staticNetFilteringEngine.freeze();
|
||||||
µb.cosmeticFilteringEngine.freeze();
|
µb.cosmeticFilteringEngine.freeze();
|
||||||
vAPI.storage.set({ 'remoteBlacklists': µb.remoteBlacklists });
|
vAPI.storage.set({ 'remoteBlacklists': µb.remoteBlacklists });
|
||||||
vAPI.messaging.broadcast({ what: 'loadUbiquitousBlacklistCompleted' });
|
vAPI.messaging.broadcast({ what: 'loadUbiquitousBlacklistCompleted' });
|
||||||
@ -296,7 +296,7 @@
|
|||||||
|
|
||||||
var loadBlacklistsStart = function(lists) {
|
var loadBlacklistsStart = function(lists) {
|
||||||
µb.remoteBlacklists = lists;
|
µb.remoteBlacklists = lists;
|
||||||
µb.netFilteringEngine.reset();
|
µb.staticNetFilteringEngine.reset();
|
||||||
µb.cosmeticFilteringEngine.reset();
|
µb.cosmeticFilteringEngine.reset();
|
||||||
µb.destroySelfie();
|
µb.destroySelfie();
|
||||||
var locations = Object.keys(lists);
|
var locations = Object.keys(lists);
|
||||||
@ -328,17 +328,17 @@
|
|||||||
µBlock.mergeFilterList = function(details) {
|
µBlock.mergeFilterList = function(details) {
|
||||||
// console.log('µBlock > mergeFilterList from "%s": "%s..."', details.path, details.content.slice(0, 40));
|
// console.log('µBlock > mergeFilterList from "%s": "%s..."', details.path, details.content.slice(0, 40));
|
||||||
|
|
||||||
var netFilteringEngine = this.netFilteringEngine;
|
var staticNetFilteringEngine = this.staticNetFilteringEngine;
|
||||||
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
||||||
var duplicateCount = netFilteringEngine.duplicateCount + cosmeticFilteringEngine.duplicateCount;
|
var duplicateCount = staticNetFilteringEngine.duplicateCount + cosmeticFilteringEngine.duplicateCount;
|
||||||
var acceptedCount = netFilteringEngine.acceptedCount + cosmeticFilteringEngine.acceptedCount;
|
var acceptedCount = staticNetFilteringEngine.acceptedCount + cosmeticFilteringEngine.acceptedCount;
|
||||||
|
|
||||||
this.mergeFilterText(details.content);
|
this.mergeFilterText(details.content);
|
||||||
|
|
||||||
// For convenience, store the number of entries for this
|
// For convenience, store the number of entries for this
|
||||||
// blacklist, user might be happy to know this information.
|
// blacklist, user might be happy to know this information.
|
||||||
duplicateCount = netFilteringEngine.duplicateCount + cosmeticFilteringEngine.duplicateCount - duplicateCount;
|
duplicateCount = staticNetFilteringEngine.duplicateCount + cosmeticFilteringEngine.duplicateCount - duplicateCount;
|
||||||
acceptedCount = netFilteringEngine.acceptedCount + cosmeticFilteringEngine.acceptedCount - acceptedCount;
|
acceptedCount = staticNetFilteringEngine.acceptedCount + cosmeticFilteringEngine.acceptedCount - acceptedCount;
|
||||||
|
|
||||||
var filterListMeta = this.remoteBlacklists[details.path];
|
var filterListMeta = this.remoteBlacklists[details.path];
|
||||||
|
|
||||||
@ -363,7 +363,7 @@
|
|||||||
// Useful references:
|
// Useful references:
|
||||||
// https://adblockplus.org/en/filter-cheatsheet
|
// https://adblockplus.org/en/filter-cheatsheet
|
||||||
// https://adblockplus.org/en/filters
|
// https://adblockplus.org/en/filters
|
||||||
var netFilteringEngine = this.netFilteringEngine;
|
var staticNetFilteringEngine = this.staticNetFilteringEngine;
|
||||||
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
||||||
var parseCosmeticFilters = this.userSettings.parseAllABPHideFilters;
|
var parseCosmeticFilters = this.userSettings.parseAllABPHideFilters;
|
||||||
|
|
||||||
@ -433,7 +433,7 @@
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
netFilteringEngine.add(matches[0]);
|
staticNetFilteringEngine.add(matches[0]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -520,7 +520,7 @@
|
|||||||
magic: this.selfieMagic,
|
magic: this.selfieMagic,
|
||||||
publicSuffixList: publicSuffixList.toSelfie(),
|
publicSuffixList: publicSuffixList.toSelfie(),
|
||||||
filterLists: this.remoteBlacklists,
|
filterLists: this.remoteBlacklists,
|
||||||
netFilteringEngine: this.netFilteringEngine.toSelfie(),
|
staticNetFilteringEngine: this.staticNetFilteringEngine.toSelfie(),
|
||||||
cosmeticFilteringEngine: this.cosmeticFilteringEngine.toSelfie()
|
cosmeticFilteringEngine: this.cosmeticFilteringEngine.toSelfie()
|
||||||
};
|
};
|
||||||
vAPI.storage.set({ selfie: selfie });
|
vAPI.storage.set({ selfie: selfie });
|
||||||
@ -565,7 +565,7 @@
|
|||||||
}
|
}
|
||||||
// console.log('µBlock.fromSelfie> selfie looks good');
|
// console.log('µBlock.fromSelfie> selfie looks good');
|
||||||
µb.remoteBlacklists = selfie.filterLists;
|
µb.remoteBlacklists = selfie.filterLists;
|
||||||
µb.netFilteringEngine.fromSelfie(selfie.netFilteringEngine);
|
µb.staticNetFilteringEngine.fromSelfie(selfie.staticNetFilteringEngine);
|
||||||
µb.cosmeticFilteringEngine.fromSelfie(selfie.cosmeticFilteringEngine);
|
µb.cosmeticFilteringEngine.fromSelfie(selfie.cosmeticFilteringEngine);
|
||||||
callback(true);
|
callback(true);
|
||||||
};
|
};
|
||||||
@ -649,12 +649,21 @@
|
|||||||
// Important: block remote fetching for when loading assets at launch
|
// Important: block remote fetching for when loading assets at launch
|
||||||
// time.
|
// time.
|
||||||
µb.assets.allowRemoteFetch = false;
|
µb.assets.allowRemoteFetch = false;
|
||||||
|
|
||||||
µb.assets.autoUpdate = settings.autoUpdate;
|
µb.assets.autoUpdate = settings.autoUpdate;
|
||||||
µb.netFilteringEngine.dynamicFiltersFromSelfie(settings.dynamicFilteringSelfie);
|
|
||||||
µb.fromSelfie(onSelfieReady);
|
µb.fromSelfie(onSelfieReady);
|
||||||
µb.mirrors.toggle(settings.experimentalEnabled);
|
µb.mirrors.toggle(settings.experimentalEnabled);
|
||||||
µb.contextMenu.toggle(settings.contextMenuEnabled);
|
µb.contextMenu.toggle(settings.contextMenuEnabled);
|
||||||
|
|
||||||
|
if ( typeof settings.dynamicFilteringSelfie === 'string' ) {
|
||||||
|
if ( settings.dynamicFilteringString === '' && settings.dynamicFilteringSelfie !== '' ) {
|
||||||
|
µb.dynamicNetFilteringEngine.fromObsoleteSelfie(settings.dynamicFilteringSelfie);
|
||||||
|
µb.userSettings.dynamicFilteringString = µb.dynamicNetFilteringEngine.toString();
|
||||||
|
µb.XAL.keyvalSetOne('dynamicFilteringString', µb.userSettings.dynamicFilteringString);
|
||||||
|
}
|
||||||
|
delete µb.userSettings.dynamicFilteringSelfie;
|
||||||
|
µb.XAL.keyvalRemoveOne('dynamicFilteringSelfie');
|
||||||
|
}
|
||||||
|
µb.dynamicNetFilteringEngine.fromString(µb.userSettings.dynamicFilteringString);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loadUserSettings(onUserSettingsReady);
|
this.loadUserSettings(onUserSettingsReady);
|
||||||
|
@ -55,6 +55,8 @@ vAPI.tabs.onClosed = function(tabId) {
|
|||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/297
|
// https://github.com/gorhill/uBlock/issues/297
|
||||||
vAPI.tabs.onPopup = function(details) {
|
vAPI.tabs.onPopup = function(details) {
|
||||||
|
//console.debug('vAPI.tabs.onPopup: url="%s"', details.url);
|
||||||
|
|
||||||
var pageStore = µBlock.pageStoreFromTabId(details.sourceTabId);
|
var pageStore = µBlock.pageStoreFromTabId(details.sourceTabId);
|
||||||
if ( !pageStore ) {
|
if ( !pageStore ) {
|
||||||
return;
|
return;
|
||||||
@ -65,7 +67,7 @@ vAPI.tabs.onPopup = function(details) {
|
|||||||
// https://github.com/gorhill/uBlock/issues/323
|
// https://github.com/gorhill/uBlock/issues/323
|
||||||
// If popup URL is whitelisted, do not block it
|
// If popup URL is whitelisted, do not block it
|
||||||
if ( µBlock.getNetFilteringSwitch(requestURL) ) {
|
if ( µBlock.getNetFilteringSwitch(requestURL) ) {
|
||||||
result = µBlock.netFilteringEngine.matchStringExactType(pageStore, requestURL, 'popup');
|
result = µBlock.staticNetFilteringEngine.matchStringExactType(pageStore, requestURL, 'popup');
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/91
|
// https://github.com/gorhill/uBlock/issues/91
|
||||||
|
@ -80,7 +80,6 @@ var onBeforeRequest = function(details) {
|
|||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/114
|
// https://github.com/gorhill/uBlock/issues/114
|
||||||
var requestContext = pageStore;
|
var requestContext = pageStore;
|
||||||
|
|
||||||
var frameStore;
|
var frameStore;
|
||||||
var frameId = details.frameId;
|
var frameId = details.frameId;
|
||||||
if ( frameId > 0 ) {
|
if ( frameId > 0 ) {
|
||||||
@ -89,7 +88,12 @@ var onBeforeRequest = function(details) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = pageStore.filterRequest(requestContext, requestType, requestURL);
|
// Setup context and evaluate
|
||||||
|
requestContext.requestURL = requestURL;
|
||||||
|
requestContext.requestHostname = µb.URI.hostnameFromURI(requestURL);
|
||||||
|
requestContext.requestType = requestType;
|
||||||
|
|
||||||
|
var result = pageStore.filterRequest(requestContext);
|
||||||
|
|
||||||
// Not blocked
|
// Not blocked
|
||||||
if ( pageStore.boolFromResult(result) === false ) {
|
if ( pageStore.boolFromResult(result) === false ) {
|
||||||
@ -208,11 +212,12 @@ var onBeforeSendHeaders = function(details) {
|
|||||||
var pageDetails = {
|
var pageDetails = {
|
||||||
pageHostname: referrerHostname,
|
pageHostname: referrerHostname,
|
||||||
pageDomain: µburi.domainFromHostname(referrerHostname),
|
pageDomain: µburi.domainFromHostname(referrerHostname),
|
||||||
|
firstParty: false
|
||||||
};
|
};
|
||||||
pageDetails.rootHostname = pageDetails.pageHostname;
|
pageDetails.rootHostname = pageDetails.pageHostname;
|
||||||
pageDetails.rootDomain = pageDetails.pageDomain;
|
pageDetails.rootDomain = pageDetails.pageDomain;
|
||||||
//console.debug('Referrer="%s"', referrer);
|
//console.debug('Referrer="%s"', referrer);
|
||||||
var result = µb.netFilteringEngine.matchStringExactType(pageDetails, requestURL, 'popup');
|
var result = µb.staticNetFilteringEngine.matchStringExactType(pageDetails, requestURL, 'popup');
|
||||||
|
|
||||||
// Not blocked?
|
// Not blocked?
|
||||||
if ( result === '' || result.slice(0, 2) === '@@' ) {
|
if ( result === '' || result.slice(0, 2) === '@@' ) {
|
||||||
@ -251,22 +256,14 @@ var onHeadersReceived = function(details) {
|
|||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/384
|
// https://github.com/gorhill/uBlock/issues/384
|
||||||
pageStore.skipLocalMirroring = headerValue(details.responseHeaders, 'content-security-policy');
|
pageStore.skipLocalMirroring = headerValue(details.responseHeaders, 'content-security-policy');
|
||||||
|
pageStore.requestURL = details.url;
|
||||||
var result = '';
|
pageStore.requestHostname = µb.URI.hostnameFromURI(details.url);
|
||||||
if ( pageStore.getNetFilteringSwitch() ) {
|
pageStore.requestType = 'inline-script';
|
||||||
result = µb.netFilteringEngine.matchStringExactType(pageStore, details.url, 'inline-script');
|
var result = pageStore.filterRequest(pageStore);
|
||||||
}
|
if ( result === '' ) {
|
||||||
|
|
||||||
// Not blocked?
|
|
||||||
if ( result === '' || result.slice(0, 2) === '@@' ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record request
|
|
||||||
if ( result !== '' ) {
|
|
||||||
pageStore.recordResult('script', details.url, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blocked
|
// Blocked
|
||||||
pageStore.perLoadBlockedRequestCount++;
|
pageStore.perLoadBlockedRequestCount++;
|
||||||
µb.localSettings.blockedRequestCount++;
|
µb.localSettings.blockedRequestCount++;
|
||||||
|
@ -309,23 +309,88 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
|||||||
µBlock.toggleDynamicFilter = function(details) {
|
µBlock.toggleDynamicFilter = function(details) {
|
||||||
var changed = false;
|
var changed = false;
|
||||||
if ( details.block ) {
|
if ( details.block ) {
|
||||||
changed = this.netFilteringEngine.dynamicFilterBlock(details.hostname, details.requestType, details.firstParty);
|
changed = this.dynamicNetFilteringEngine.blockCell(details.srcHostname, details.desHostname, details.requestType);
|
||||||
} else {
|
} else {
|
||||||
changed = this.netFilteringEngine.dynamicFilterUnblock(details.hostname, details.requestType, details.firstParty);
|
changed = this.dynamicNetFilteringEngine.unsetCell(details.srcHostname, details.desHostname, details.requestType);
|
||||||
}
|
}
|
||||||
if ( !changed ) {
|
if ( !changed ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.userSettings.dynamicFilteringSelfie = this.netFilteringEngine.selfieFromDynamicFilters();
|
this.userSettings.dynamicFilteringString = this.dynamicNetFilteringEngine.toString();
|
||||||
this.XAL.keyvalSetOne('dynamicFilteringSelfie', this.userSettings.dynamicFilteringSelfie);
|
this.XAL.keyvalSetOne('dynamicFilteringString', this.userSettings.dynamicFilteringString);
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/420
|
// https://github.com/gorhill/uBlock/issues/420
|
||||||
if ( details.requestType === 'sub_frame' && !details.block ) {
|
if ( details.requestType === '3p-frame' && !details.block ) {
|
||||||
this.cosmeticFilteringEngine.removeFromSelectorCache(details.hostname, 'net');
|
this.cosmeticFilteringEngine.removeFromSelectorCache(details.hostname, 'net');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.isFirstParty = function(firstPartyDomain, hostname) {
|
||||||
|
if ( hostname.slice(0 - firstPartyDomain.length) !== firstPartyDomain ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Be sure to not confuse 'example.com' with 'anotherexample.com'
|
||||||
|
var c = hostname.charAt(hostname.length - firstPartyDomain.length - 1);
|
||||||
|
return c === '.' || c === '';
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// The core logic to evaluate requests through dynamic/static filtering
|
||||||
|
// is here.
|
||||||
|
|
||||||
|
µBlock.filterRequest = function(context) {
|
||||||
|
// Given that:
|
||||||
|
// - Dynamic filtering override static filtering
|
||||||
|
// - Evaluating dynamic filtering is much faster than static filtering
|
||||||
|
// We evaluate dynamic filtering first, and hopefully we can skip
|
||||||
|
// evaluation of static filtering.
|
||||||
|
// Dynamic filtering evaluation is ordered from most-specific to least-
|
||||||
|
// specific.
|
||||||
|
var df = this.dynamicNetFilteringEngine;
|
||||||
|
var rootHostname = context.rootHostname;
|
||||||
|
var requestHostname = context.requestHostname;
|
||||||
|
var requestType = context.requestType;
|
||||||
|
|
||||||
|
// Dynamic filters:
|
||||||
|
// 1. specific source, specific destination, any type, allow/block
|
||||||
|
// 2. any source, specific destination, any type, allow/block
|
||||||
|
df.evaluateCellZY(rootHostname, requestHostname, '*');
|
||||||
|
if ( df.mustBlockOrAllow() ) {
|
||||||
|
return df.toFilterString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamic filters:
|
||||||
|
// 3. specific source, any destination, specific type, allow/block
|
||||||
|
// 4. any source, any destination, specific type, allow/block
|
||||||
|
if ( requestType === 'script' ) {
|
||||||
|
df.evaluateCellZY(rootHostname, requestHostname, this.isFirstParty(rootHostname, requestHostname) ? '1p-script' : '3p-script');
|
||||||
|
if ( df.mustBlockOrAllow() ) {
|
||||||
|
return df.toFilterString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( requestType === 'sub_frame' ) {
|
||||||
|
if ( this.isFirstParty(rootHostname, requestHostname) === false ) {
|
||||||
|
df.evaluateCellZY(rootHostname, requestHostname, '3p-frame');
|
||||||
|
if ( df.mustBlockOrAllow() ) {
|
||||||
|
return df.toFilterString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
df.evaluateCellZY(rootHostname, requestHostname, requestType);
|
||||||
|
if ( df.mustBlockOrAllow() ) {
|
||||||
|
return df.toFilterString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Static filtering never override dynamic filtering
|
||||||
|
return this.staticNetFilteringEngine.matchString(context);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
})();
|
})();
|
@ -48,6 +48,12 @@ exports.keyvalSetMany = function(dict, callback) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
exports.keyvalRemoveOne = function(key, callback) {
|
||||||
|
vAPI.storage.remove(key, callback || noopFunc);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
exports.keyvalRemoveAll = function(callback) {
|
exports.keyvalRemoveAll = function(callback) {
|
||||||
vAPI.storage.clear(callback || noopFunc);
|
vAPI.storage.clear(callback || noopFunc);
|
||||||
};
|
};
|
||||||
|
@ -11,9 +11,17 @@
|
|||||||
<body>
|
<body>
|
||||||
<h4 title="popupTipDashboard">v<span id="version"></span></h4>
|
<h4 title="popupTipDashboard">v<span id="version"></span></h4>
|
||||||
<div>
|
<div>
|
||||||
|
<div id="dynamicFilteringContainer">
|
||||||
|
<div><span>images</span><span data-src="*" data-des="*" data-type="image"></span><span data-src="local" data-des="*" data-type="image"></span></div>
|
||||||
|
<div><span>inline scripts</span><span data-src="*" data-des="*" data-type="inline-script"></span><span data-src="local" data-des="*" data-type="inline-script"></span></div>
|
||||||
|
<div><span>1st-party scripts</span><span data-src="*" data-des="*" data-type="1p-script"></span><span data-src="local" data-des="*" data-type="1p-script"></span></div>
|
||||||
|
<div><span>3rd-party scripts</span><span data-src="*" data-des="*" data-type="3p-script"></span><span data-src="local" data-des="*" data-type="3p-script"></span></div>
|
||||||
|
<div><span>3rd-party frames</span><span data-src="*" data-des="*" data-type="3p-frame"></span><span data-src="local" data-des="*" data-type="3p-frame"></span></div>
|
||||||
|
</div>
|
||||||
|
</div><!-- DO NOT REMOVE --><div>
|
||||||
<p id="switch" data-i18n-tip="popupPowerSwitchInfo"><span class="fa"></span></p>
|
<p id="switch" data-i18n-tip="popupPowerSwitchInfo"><span class="fa"></span></p>
|
||||||
<p id="switch-hint"></p>
|
<p id="switch-hint"></p>
|
||||||
<p style="font-size: 16px;" data-i18n="popupBlockedRequestPrompt"></p>
|
<p id="dynamicFilteringToggler" data-i18n="popupBlockedRequestPrompt"></p>
|
||||||
<p id="stats">
|
<p id="stats">
|
||||||
<span data-i18n="popupBlockedOnThisPagePrompt"></span> 
|
<span data-i18n="popupBlockedOnThisPagePrompt"></span> 
|
||||||
<span id="gotoPick" class="fa tool" data-i18n-tip="popupTipPicker" data-tip-anchor="top"></span> 
|
<span id="gotoPick" class="fa tool" data-i18n-tip="popupTipPicker" data-tip-anchor="top"></span> 
|
||||||
@ -24,65 +32,6 @@
|
|||||||
<p id="total-blocked">?</p>
|
<p id="total-blocked">?</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="dynamicFilteringToggler" class="fa">
|
|
||||||
<div></div>
|
|
||||||
<div></div>
|
|
||||||
<div></div>
|
|
||||||
<div></div>
|
|
||||||
<a href="https://github.com/gorhill/uBlock/wiki/Dynamic-filtering" target="_blank">?</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="dynamicFilteringContainer">
|
|
||||||
<div class="dynamicFiltering local" data-scope=".">
|
|
||||||
<div data-first-party data-type="inline-script">
|
|
||||||
<div class="tip" data-i18n="popupSiteInlineScriptEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupSiteInlineScriptDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div data-first-party data-type="script">
|
|
||||||
<div class="tip" data-i18n="popupSite1pScriptEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupSite1pScriptDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div data-type="script">
|
|
||||||
<div class="tip" data-i18n="popupSite3pScriptEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupSite3pScriptDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div data-first-party data-type="sub_frame">
|
|
||||||
<div class="tip" data-i18n="popupSite1pFrameEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupSite1pFrameDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div data-type="sub_frame">
|
|
||||||
<div class="tip" data-i18n="popupSite3pFrameEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupSite3pFrameDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div class="label"><script></div>
|
|
||||||
<div class="label"><iframe></div>
|
|
||||||
</div>
|
|
||||||
<div class="dynamicFiltering global" data-scope="/">
|
|
||||||
<div data-first-party data-type="inline-script">
|
|
||||||
<div class="tip" data-i18n="popupDefaultInlineScriptEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupDefaultInlineScriptDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div data-first-party data-type="script">
|
|
||||||
<div class="tip" data-i18n="popupDefault1pScriptEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupDefault1pScriptDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div data-type="script">
|
|
||||||
<div class="tip" data-i18n="popupDefault3pScriptEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupDefault3pScriptDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div data-first-party data-type="sub_frame">
|
|
||||||
<div class="tip" data-i18n="popupDefault1pFrameEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupDefault1pFrameDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div data-type="sub_frame">
|
|
||||||
<div class="tip" data-i18n="popupDefault3pFrameEnabled"></div>
|
|
||||||
<div class="tip" data-i18n="popupDefault3pFrameDisabled"></div>
|
|
||||||
</div>
|
|
||||||
<div class="label"><script></div>
|
|
||||||
<div class="label"><iframe></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script src="js/vapi-common.js"></script>
|
<script src="js/vapi-common.js"></script>
|
||||||
<script src="js/vapi-client.js"></script>
|
<script src="js/vapi-client.js"></script>
|
||||||
<script src="js/udom.js"></script>
|
<script src="js/udom.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user