mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-26 04:12:50 +01:00
Additionally, there has been refactoring work done regarding filtering context used throughout uBO, motivated by the fix here.
This commit is contained in:
parent
a629dbdd08
commit
9b27a98f90
@ -282,21 +282,12 @@ vAPI.tabs = {};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/3546
|
||||
// Added a new flavor of behind-the-scene tab id: vAPI.anyTabId.
|
||||
// vAPI.anyTabId will be used for network requests which can be filtered,
|
||||
// because they comes with enough contextual information. It's just not
|
||||
// possible to pinpoint exactly from which tab it comes from. For example,
|
||||
// with Firefox/webext, the `documentUrl` property is available for every
|
||||
// network requests.
|
||||
|
||||
vAPI.isBehindTheSceneTabId = function(tabId) {
|
||||
return tabId < 0;
|
||||
};
|
||||
|
||||
vAPI.unsetTabId = 0;
|
||||
vAPI.noTabId = -1; // definitely not any existing tab
|
||||
vAPI.anyTabId = -2; // one of the existing tab
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -74,11 +74,9 @@
|
||||
// Chromium 63+ supports the `initiator` property, which contains
|
||||
// the URL of the origin from which the network request was made.
|
||||
if (
|
||||
details.tabId === vAPI.noTabId &&
|
||||
typeof details.initiator === 'string' &&
|
||||
details.initiator !== 'null'
|
||||
) {
|
||||
details.tabId = vAPI.anyTabId;
|
||||
details.documentUrl = details.initiator;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2017-2018 Raymond Hill
|
||||
Copyright (C) 2017-present 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
|
||||
@ -66,13 +66,6 @@
|
||||
let parsedURL = new URL('about:blank');
|
||||
|
||||
vAPI.net.normalizeDetails = function(details) {
|
||||
if (
|
||||
details.tabId === vAPI.noTabId &&
|
||||
typeof details.documentUrl === 'string'
|
||||
) {
|
||||
details.tabId = vAPI.anyTabId;
|
||||
}
|
||||
|
||||
if ( mustPunycode && !reAsciiHostname.test(details.url) ) {
|
||||
parsedURL.href = details.url;
|
||||
details.url = details.url.replace(
|
||||
|
@ -85,13 +85,11 @@ vAPI.net.registerListeners = function() {
|
||||
// Chromium uses `initiator` property.
|
||||
if (
|
||||
details.documentUrl === undefined &&
|
||||
typeof details.initiator === 'string'
|
||||
typeof details.initiator === 'string' &&
|
||||
details.initiator !== 'null'
|
||||
) {
|
||||
details.documentUrl = details.initiator;
|
||||
}
|
||||
if ( typeof details.documentUrl === 'string' ) {
|
||||
details.tabId = vAPI.anyTabId;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1493
|
||||
|
@ -536,7 +536,7 @@
|
||||
"description":"Appears in the logger's tab selector"
|
||||
},
|
||||
"logBehindTheScene":{
|
||||
"message":"Behind the scene",
|
||||
"message":"Tabless",
|
||||
"description":"Pretty name for behind-the-scene network requests"
|
||||
},
|
||||
"loggerCurrentTab":{
|
||||
|
@ -20,6 +20,7 @@
|
||||
<script src="js/lz4.js"></script>
|
||||
<script src="js/cachestorage.js"></script>
|
||||
<script src="js/assets.js"></script>
|
||||
<script src="js/filtering-context.js"></script>
|
||||
<script src="js/redirect-engine.js"></script>
|
||||
<script src="js/dynamic-net-filtering.js"></script>
|
||||
<script src="js/static-net-filtering.js"></script>
|
||||
|
@ -16,9 +16,11 @@ textarea {
|
||||
width: 100%;
|
||||
}
|
||||
.permatoolbar {
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
border: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
font-size: 120%;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
@ -28,14 +30,15 @@ textarea {
|
||||
z-index: 10;
|
||||
}
|
||||
.permatoolbar .button {
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
font-size: 150%;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
padding: 0.25em;
|
||||
}
|
||||
.permatoolbar .button.disabled {
|
||||
opacity: 0.2;
|
||||
@ -54,8 +57,14 @@ textarea {
|
||||
vertical-align: middle;
|
||||
}
|
||||
#pageSelector {
|
||||
margin-right: 1em;
|
||||
padding: 0.25em 0;
|
||||
width: 28em;
|
||||
padding: 0.2em 0;
|
||||
}
|
||||
#showpopup img {
|
||||
filter: grayscale(100%);
|
||||
height: auto;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -128,19 +137,22 @@ textarea {
|
||||
width: 4.6em;
|
||||
}
|
||||
#netInspector table > colgroup > col:nth-of-type(2) {
|
||||
width: 2.1em;
|
||||
width: 16%;
|
||||
}
|
||||
#netInspector table > colgroup > col:nth-of-type(3) {
|
||||
width: 20%;
|
||||
}
|
||||
#netInspector table > colgroup > col:nth-of-type(4) {
|
||||
width: 2.1em;
|
||||
}
|
||||
#netInspector table > colgroup > col:nth-of-type(4) {
|
||||
width: 20%;
|
||||
}
|
||||
#netInspector table > colgroup > col:nth-of-type(5) {
|
||||
width: 5.8em;
|
||||
width: 2.4em;
|
||||
}
|
||||
#netInspector table > colgroup > col:nth-of-type(6) {
|
||||
width: calc(100% - 14.6em - 20%);
|
||||
width: 6em;
|
||||
}
|
||||
#netInspector table > colgroup > col:nth-of-type(7) {
|
||||
width: calc(100% - 4.6em - 16% - 2.1em - 20% - 2.4em - 6em);
|
||||
}
|
||||
#netInspector.f table tr.f {
|
||||
display: none;
|
||||
@ -205,6 +217,12 @@ body #netInspector td {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#netInspector tr[data-tabid].void {
|
||||
opacity: 0.3;
|
||||
}
|
||||
#netInspector tr[data-tabid].void:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#netInspector tr td:nth-of-type(1) {
|
||||
cursor: default;
|
||||
@ -212,68 +230,71 @@ body #netInspector td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
#netInspector tr td:nth-of-type(2) {
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#netInspector tr.tab_bts > td:nth-of-type(2):before {
|
||||
content: '\f070';
|
||||
font: 1em FontAwesome;
|
||||
}
|
||||
#netInspector tr.tab:not(.canMtx) {
|
||||
opacity: 0.3;
|
||||
}
|
||||
#netInspector tr.tab:not(.canMtx):hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
#netInspector tr.tab:not(.canMtx) > td:nth-of-type(2):before {
|
||||
content: '\f00d';
|
||||
font: 1em FontAwesome;
|
||||
}
|
||||
body:not(.popupOn) #netInspector tr.canMtx td:nth-of-type(2) {
|
||||
#netInspector tr.canLookup td:nth-of-type(2) {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
body:not(.popupOn) #netInspector tr.canMtx td:nth-of-type(2):hover {
|
||||
background: #ccc;
|
||||
}
|
||||
#netInspector tr.canLookup td:nth-of-type(3) {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
#netInspector tr.cat_net td:nth-of-type(4),
|
||||
#netInspector tr.cat_cosmetic td:nth-of-type(4),
|
||||
#netInspector tr.cat_redirect td:nth-of-type(4) {
|
||||
#netInspector tr.cat_net td:nth-of-type(3),
|
||||
#netInspector tr.cat_cosmetic td:nth-of-type(3),
|
||||
#netInspector tr.cat_redirect td:nth-of-type(3) {
|
||||
font: 12px monospace;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#netInspector tr.cat_net td:nth-of-type(4) {
|
||||
#netInspector tr.cat_net td:nth-of-type(3) {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
#netInspector tr.cat_net td:nth-of-type(4):hover {
|
||||
#netInspector tr.cat_net td:nth-of-type(3):hover {
|
||||
background: #ccc;
|
||||
}
|
||||
#netInspector tr.cat_net td:nth-of-type(6) > span > b {
|
||||
#netInspector tr td:nth-of-type(4) {
|
||||
}
|
||||
#netInspector tr[data-dochn] td:nth-of-type(4) {
|
||||
direction: rtl;
|
||||
}
|
||||
#netInspector tr td:nth-of-type(5) {
|
||||
cursor: default;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
#netInspector tr.tab_bts td:nth-of-type(5)::after {
|
||||
border: 5px solid #bbb;
|
||||
border-bottom: 0;
|
||||
border-top: 0;
|
||||
bottom: 0;
|
||||
content: '\00a0';
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: calc(100% - 10px);
|
||||
z-index: -1;
|
||||
}
|
||||
#netInspector tr td:nth-of-type(6) {
|
||||
text-align: right;
|
||||
}
|
||||
#netInspector tr.cat_net td:nth-of-type(7) > span > b {
|
||||
font-weight: bold;
|
||||
}
|
||||
#netInspector tr td:nth-of-type(6) b {
|
||||
#netInspector tr td:nth-of-type(7) b {
|
||||
font-weight: normal;
|
||||
}
|
||||
#netInspector tr.blocked td:nth-of-type(6) b {
|
||||
#netInspector tr.blocked td:nth-of-type(7) b {
|
||||
background-color: rgba(192, 0, 0, 0.2);
|
||||
}
|
||||
body.colorBlind #netInspector tr.blocked td:nth-of-type(6) b {
|
||||
body.colorBlind #netInspector tr.blocked td:nth-of-type(7) b {
|
||||
background-color: rgba(0, 19, 110, 0.2);
|
||||
}
|
||||
#netInspector tr.nooped td:nth-of-type(6) b {
|
||||
#netInspector tr.nooped td:nth-of-type(7) b {
|
||||
background-color: rgba(108, 108, 108, 0.2);
|
||||
}
|
||||
body.colorBlind #netInspector tr.nooped td:nth-of-type(6) b {
|
||||
body.colorBlind #netInspector tr.nooped td:nth-of-type(7) b {
|
||||
background-color: rgba(96, 96, 96, 0.2);
|
||||
}
|
||||
#netInspector tr.allowed td:nth-of-type(6) b {
|
||||
#netInspector tr.allowed td:nth-of-type(7) b {
|
||||
background-color: rgba(0, 160, 0, 0.2);
|
||||
}
|
||||
body.colorBlind #netInspector tr.allowed td:nth-of-type(6) b {
|
||||
body.colorBlind #netInspector tr.allowed td:nth-of-type(7) b {
|
||||
background-color: rgba(255, 194, 57, 0.2);
|
||||
}
|
||||
|
||||
@ -281,49 +302,17 @@ body.colorBlind #netInspector tr.allowed td:nth-of-type(6) b {
|
||||
background: white;
|
||||
border: 1px solid gray;
|
||||
border-radius: 3px;
|
||||
bottom: 0;
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
}
|
||||
#netInspector.popupOn #popupContainer {
|
||||
#inspectors.popupOn #popupContainer {
|
||||
display: block;
|
||||
}
|
||||
#popupContainer > div {
|
||||
background: #aaa;
|
||||
border: 0;
|
||||
}
|
||||
body[dir="ltr"] #popupContainer > div {
|
||||
text-align: right;
|
||||
}
|
||||
body[dir="rtl"] #popupContainer > div {
|
||||
text-align: left;
|
||||
}
|
||||
#popupContainer > div > span {
|
||||
color: #eee;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font: 14px FontAwesome;
|
||||
padding: 0 3px;
|
||||
}
|
||||
#popupContainer > div > span:hover {
|
||||
color: white;
|
||||
}
|
||||
#popupContainer > iframe {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
#popupContainer.hide {
|
||||
width: 6em !important;
|
||||
}
|
||||
#popupContainer.hide > iframe {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modalDialog {
|
||||
align-items: center;
|
||||
|
@ -27,13 +27,12 @@
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var reIsExternalPath = /^(?:[a-z-]+):\/\//,
|
||||
const reIsExternalPath = /^(?:[a-z-]+):\/\//,
|
||||
reIsUserAsset = /^user-/,
|
||||
errorCantConnectTo = vAPI.i18n('errorCantConnectTo'),
|
||||
noopfunc = function(){};
|
||||
|
||||
var api = {
|
||||
};
|
||||
const api = {};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@ -64,14 +63,14 @@ var fireNotification = function(topic, details) {
|
||||
/******************************************************************************/
|
||||
|
||||
api.fetchText = function(url, onLoad, onError) {
|
||||
var isExternal = reIsExternalPath.test(url),
|
||||
actualUrl = isExternal ? url : vAPI.getURL(url);
|
||||
const isExternal = reIsExternalPath.test(url);
|
||||
let actualUrl = isExternal ? url : vAPI.getURL(url);
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/2592
|
||||
// Force browser cache to be bypassed, but only for resources which have
|
||||
// been fetched more than one hour ago.
|
||||
if ( isExternal ) {
|
||||
var queryValue = '_=' + Math.floor(Date.now() / 7200000);
|
||||
const queryValue = '_=' + Math.floor(Date.now() / 7200000);
|
||||
if ( actualUrl.indexOf('?') === -1 ) {
|
||||
actualUrl += '?';
|
||||
} else {
|
||||
@ -84,12 +83,12 @@ api.fetchText = function(url, onLoad, onError) {
|
||||
onError = onLoad;
|
||||
}
|
||||
|
||||
var contentLoaded = 0,
|
||||
timeoutAfter = µBlock.hiddenSettings.assetFetchTimeout * 1000 || 30000,
|
||||
timeoutTimer,
|
||||
xhr = new XMLHttpRequest();
|
||||
const timeoutAfter = µBlock.hiddenSettings.assetFetchTimeout * 1000 || 30000;
|
||||
const xhr = new XMLHttpRequest();
|
||||
let contentLoaded = 0;
|
||||
let timeoutTimer;
|
||||
|
||||
var cleanup = function() {
|
||||
const cleanup = function() {
|
||||
xhr.removeEventListener('load', onLoadEvent);
|
||||
xhr.removeEventListener('error', onErrorEvent);
|
||||
xhr.removeEventListener('abort', onErrorEvent);
|
||||
@ -101,11 +100,11 @@ api.fetchText = function(url, onLoad, onError) {
|
||||
};
|
||||
|
||||
// https://github.com/gorhill/uMatrix/issues/15
|
||||
var onLoadEvent = function() {
|
||||
const onLoadEvent = function() {
|
||||
cleanup();
|
||||
// xhr for local files gives status 0, but actually succeeds
|
||||
var details = {
|
||||
url: url,
|
||||
const details = {
|
||||
url,
|
||||
content: '',
|
||||
statusCode: this.status || 200,
|
||||
statusText: this.statusText || ''
|
||||
@ -120,7 +119,7 @@ api.fetchText = function(url, onLoad, onError) {
|
||||
// we never download anything else than plain text: discard if response
|
||||
// appears to be a HTML document: could happen when server serves
|
||||
// some kind of error page I suppose
|
||||
var text = this.responseText.trim();
|
||||
const text = this.responseText.trim();
|
||||
if ( text.startsWith('<') && text.endsWith('>') ) {
|
||||
return onError.call(null, details);
|
||||
}
|
||||
@ -128,19 +127,21 @@ api.fetchText = function(url, onLoad, onError) {
|
||||
onLoad(details);
|
||||
};
|
||||
|
||||
var onErrorEvent = function() {
|
||||
const onErrorEvent = function() {
|
||||
cleanup();
|
||||
µBlock.logger.writeOne('', 'error', errorCantConnectTo.replace('{{msg}}', actualUrl));
|
||||
onError({ url: url, content: '' });
|
||||
µBlock.logger.writeOne({
|
||||
error: errorCantConnectTo.replace('{{msg}}', actualUrl)
|
||||
});
|
||||
onError({ url, content: '' });
|
||||
};
|
||||
|
||||
var onTimeout = function() {
|
||||
const onTimeout = function() {
|
||||
xhr.abort();
|
||||
};
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/2526
|
||||
// - Timeout only when there is no progress.
|
||||
var onProgressEvent = function(ev) {
|
||||
const onProgressEvent = function(ev) {
|
||||
if ( ev.loaded === contentLoaded ) { return; }
|
||||
contentLoaded = ev.loaded;
|
||||
if ( timeoutTimer !== undefined ) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2014-2018 Raymond Hill
|
||||
Copyright (C) 2014-present 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
|
||||
@ -579,8 +579,11 @@ FilterContainer.prototype.compileGenericSelector = function(parsed, writer) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.compileGenericHideSelector = function(parsed, writer) {
|
||||
let selector = parsed.suffix;
|
||||
FilterContainer.prototype.compileGenericHideSelector = function(
|
||||
parsed,
|
||||
writer
|
||||
) {
|
||||
const selector = parsed.suffix;
|
||||
|
||||
// For some selectors, it is mandatory to have a hostname or entity:
|
||||
// ##.foo:-abp-contains(...)
|
||||
@ -596,18 +599,16 @@ FilterContainer.prototype.compileGenericHideSelector = function(parsed, writer)
|
||||
// ##:xpath(...)
|
||||
// ##.foo:style(...)
|
||||
if ( this.reNeedHostname.test(selector) ) {
|
||||
µb.logger.writeOne(
|
||||
'',
|
||||
'error',
|
||||
'Cosmetic filtering – invalid generic filter: ##' + selector
|
||||
);
|
||||
µb.logger.writeOne({
|
||||
error: 'Cosmetic filtering – invalid generic filter: ##' + selector
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let type = selector.charCodeAt(0);
|
||||
|
||||
if ( type === 0x23 /* '#' */ ) {
|
||||
let key = this.keyFromSelector(selector);
|
||||
const key = this.keyFromSelector(selector);
|
||||
if ( key === undefined ) { return; }
|
||||
// Simple selector-based CSS rule: no need to test for whether the
|
||||
// selector is valid, the regex took care of this. Most generic
|
||||
@ -624,7 +625,7 @@ FilterContainer.prototype.compileGenericHideSelector = function(parsed, writer)
|
||||
}
|
||||
|
||||
if ( type === 0x2E /* '.' */ ) {
|
||||
let key = this.keyFromSelector(selector);
|
||||
const key = this.keyFromSelector(selector);
|
||||
if ( key === undefined ) { return; }
|
||||
// Simple selector-based CSS rule: no need to test for whether the
|
||||
// selector is valid, the regex took care of this. Most generic
|
||||
@ -640,16 +641,16 @@ FilterContainer.prototype.compileGenericHideSelector = function(parsed, writer)
|
||||
return;
|
||||
}
|
||||
|
||||
let compiled = µb.staticExtFilteringEngine.compileSelector(selector);
|
||||
const compiled = µb.staticExtFilteringEngine.compileSelector(selector);
|
||||
if ( compiled === undefined ) { return; }
|
||||
// TODO: Detect and error on procedural cosmetic filters.
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/909
|
||||
// Anything which contains a plain id/class selector can be classified
|
||||
// as a low generic cosmetic filter.
|
||||
let matches = this.rePlainSelectorEx.exec(selector);
|
||||
const matches = this.rePlainSelectorEx.exec(selector);
|
||||
if ( matches !== null ) {
|
||||
let key = matches[1] || matches[2];
|
||||
const key = matches[1] || matches[2];
|
||||
type = key.charCodeAt(0);
|
||||
writer.push([
|
||||
type === 0x23 ? 1 : 3 /* lg+ */,
|
||||
|
282
src/js/filtering-context.js
Normal file
282
src/js/filtering-context.js
Normal file
@ -0,0 +1,282 @@
|
||||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2018-present 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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.FilteringContext = function(other) {
|
||||
if ( other instanceof µBlock.FilteringContext ) {
|
||||
return this.fromFilteringContext(other);
|
||||
}
|
||||
this.tstamp = 0;
|
||||
this.realm = '';
|
||||
this.type = undefined;
|
||||
this.url = undefined;
|
||||
this.hostname = undefined;
|
||||
this.domain = undefined;
|
||||
this.docId = undefined;
|
||||
this.docOrigin = undefined;
|
||||
this.docHostname = undefined;
|
||||
this.docDomain = undefined;
|
||||
this.tabId = undefined;
|
||||
this.tabOrigin = undefined;
|
||||
this.tabHostname = undefined;
|
||||
this.tabDomain = undefined;
|
||||
this.filter = undefined;
|
||||
};
|
||||
|
||||
µBlock.FilteringContext.prototype = {
|
||||
fromTabId: function(tabId) {
|
||||
if ( tabId !== -1 || tabId !== this.tabId ) {
|
||||
const tabContext = µBlock.tabContextManager.mustLookup(tabId);
|
||||
this.tabOrigin = tabContext.origin;
|
||||
this.tabHostname = tabContext.rootHostname;
|
||||
this.tabDomain = tabContext.rootDomain;
|
||||
this.tabId = tabId;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
fromWebrequestDetails: function(details) {
|
||||
const tabId = details.tabId;
|
||||
if ( tabId > 0 && details.type === 'main_frame' ) {
|
||||
µBlock.tabContextManager.push(tabId, details.url);
|
||||
}
|
||||
this.fromTabId(tabId);
|
||||
this.realm = '';
|
||||
this.type = details.type;
|
||||
this.setURL(details.url);
|
||||
this.docId = details.type !== 'sub_frame'
|
||||
? details.frameId
|
||||
: details.parentFrameId;
|
||||
if ( this.tabId > 0 ) {
|
||||
if ( this.docId === 0 ) {
|
||||
this.docOrigin = this.tabOrigin;
|
||||
this.docHostname = this.tabHostname;
|
||||
this.docDomain = this.tabDomain;
|
||||
} else if ( details.documentUrl !== undefined ) {
|
||||
this.setDocOriginFromURL(details.documentUrl);
|
||||
} else {
|
||||
const pageStore = µBlock.pageStoreFromTabId(this.docId);
|
||||
const docStore = pageStore && pageStore.frames.get(this.docId);
|
||||
if ( docStore ) {
|
||||
this.docOrigin = undefined;
|
||||
this.docHostname = docStore.pageHostname;
|
||||
this.docDomain = docStore.pageDomain;
|
||||
}
|
||||
}
|
||||
} else if ( details.documentUrl !== undefined ) {
|
||||
this.setTabOriginFromURL(details.documentUrl);
|
||||
this.setDocOriginFromURL(details.documentUrl);
|
||||
} else {
|
||||
this.setDocOrigin(this.tabOrigin);
|
||||
}
|
||||
this.filter = undefined;
|
||||
return this;
|
||||
},
|
||||
fromFilteringContext: function(other) {
|
||||
this.realm = other.realm;
|
||||
this.type = other.type;
|
||||
this.url = other.url;
|
||||
this.hostname = other.hostname;
|
||||
this.domain = other.domain;
|
||||
this.docId = other.docId;
|
||||
this.docOrigin = other.docOrigin;
|
||||
this.docHostname = other.docHostname;
|
||||
this.docDomain = other.docDomain;
|
||||
this.tabId = other.tabId;
|
||||
this.tabOrigin = other.tabOrigin;
|
||||
this.tabHostname = other.tabHostname;
|
||||
this.tabDomain = other.tabDomain;
|
||||
this.filter = undefined;
|
||||
return this;
|
||||
},
|
||||
duplicate: function() {
|
||||
return (new µBlock.FilteringContext(this));
|
||||
},
|
||||
setRealm: function(a) {
|
||||
this.realm = a;
|
||||
return this;
|
||||
},
|
||||
setType: function(a) {
|
||||
this.type = a;
|
||||
return this;
|
||||
},
|
||||
setURL: function(a) {
|
||||
if ( a !== this.url ) {
|
||||
this.hostname = this.domain = undefined;
|
||||
this.url = a;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
getHostname: function() {
|
||||
if ( this.hostname === undefined ) {
|
||||
this.hostname = this.hostnameFromURI(this.url);
|
||||
}
|
||||
return this.hostname;
|
||||
},
|
||||
setHostname: function(a) {
|
||||
if ( a !== this.hostname ) {
|
||||
this.domain = undefined;
|
||||
this.hostname = a;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
getDomain: function() {
|
||||
if ( this.domain === undefined ) {
|
||||
this.domain = this.domainFromHostname(this.getHostname());
|
||||
}
|
||||
return this.domain;
|
||||
},
|
||||
setDomain: function(a) {
|
||||
this.domain = a;
|
||||
return this;
|
||||
},
|
||||
getDocOrigin: function() {
|
||||
if ( this.docOrigin === undefined ) {
|
||||
this.docOrigin = this.tabOrigin;
|
||||
}
|
||||
return this.docOrigin;
|
||||
},
|
||||
setDocOrigin: function(a) {
|
||||
if ( a !== this.docOrigin ) {
|
||||
this.docHostname = this.docDomain = undefined;
|
||||
this.docOrigin = a;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
setDocOriginFromURL: function(a) {
|
||||
return this.setDocOrigin(this.originFromURI(a));
|
||||
},
|
||||
getDocHostname: function() {
|
||||
if ( this.docHostname === undefined ) {
|
||||
this.docHostname = this.hostnameFromURI(this.getDocOrigin());
|
||||
}
|
||||
return this.docHostname;
|
||||
},
|
||||
setDocHostname: function(a) {
|
||||
if ( a !== this.docHostname ) {
|
||||
this.docDomain = undefined;
|
||||
this.docHostname = a;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
getDocDomain: function() {
|
||||
if ( this.docDomain === undefined ) {
|
||||
this.docDomain = this.domainFromHostname(this.getDocHostname());
|
||||
}
|
||||
return this.docDomain;
|
||||
},
|
||||
setDocDomain: function(a) {
|
||||
this.docDomain = a;
|
||||
return this;
|
||||
},
|
||||
// The idea is to minimize the amout of work done to figure out whether
|
||||
// the resource is 3rd-party to the document.
|
||||
is3rdPartyToDoc: function() {
|
||||
const docDomain = this.getDocDomain();
|
||||
if ( this.domain !== undefined ) { return this.domain !== docDomain; }
|
||||
const hostname = this.getHostname();
|
||||
if ( hostname.endsWith(docDomain) === false ) { return true; }
|
||||
const i = hostname.length - docDomain.length;
|
||||
if ( i === 0 ) { return false; }
|
||||
return hostname.charCodeAt(i - 1) !== 0x2E /* '.' */;
|
||||
},
|
||||
setTabId: function(a) {
|
||||
this.tabId = a;
|
||||
return this;
|
||||
},
|
||||
getTabOrigin: function() {
|
||||
if ( this.tabOrigin === undefined ) {
|
||||
const tabContext = µBlock.tabContextManager.mustLookup(this.tabId);
|
||||
this.tabOrigin = tabContext.origin;
|
||||
this.tabHostname = tabContext.rootHostname;
|
||||
this.tabDomain = tabContext.rootDomain;
|
||||
}
|
||||
return this.tabOrigin;
|
||||
},
|
||||
setTabOrigin: function(a) {
|
||||
if ( a !== this.tabOrigin ) {
|
||||
this.tabHostname = this.tabDomain = undefined;
|
||||
this.tabOrigin = a;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
setTabOriginFromURL: function(a) {
|
||||
return this.setTabOrigin(this.originFromURI(a));
|
||||
},
|
||||
getTabHostname: function() {
|
||||
if ( this.tabHostname === undefined ) {
|
||||
this.tabHostname = this.hostnameFromURI(this.getTabOrigin());
|
||||
}
|
||||
return this.tabHostname;
|
||||
},
|
||||
setTabHostname: function(a) {
|
||||
if ( a !== this.tabHostname ) {
|
||||
this.tabDomain = undefined;
|
||||
this.tabHostname = a;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
getTabDomain: function() {
|
||||
if ( this.tabDomain === undefined ) {
|
||||
this.tabDomain = this.domainFromHostname(this.getTabHostname());
|
||||
}
|
||||
return this.tabDomain;
|
||||
},
|
||||
setTabDomain: function(a) {
|
||||
this.docDomain = a;
|
||||
return this;
|
||||
},
|
||||
// The idea is to minimize the amout of work done to figure out whether
|
||||
// the resource is 3rd-party to the top document.
|
||||
is3rdPartyToTab: function() {
|
||||
const tabDomain = this.getTabDomain();
|
||||
if ( this.domain !== undefined ) { return this.domain !== tabDomain; }
|
||||
const hostname = this.getHostname();
|
||||
if ( hostname.endsWith(tabDomain) === false ) { return true; }
|
||||
const i = hostname.length - tabDomain.length;
|
||||
if ( i === 0 ) { return false; }
|
||||
return hostname.charCodeAt(i - 1) !== 0x2E /* '.' */;
|
||||
},
|
||||
setFilter: function(a) {
|
||||
this.filter = a;
|
||||
return this;
|
||||
},
|
||||
toLogger: function() {
|
||||
this.tstamp = Date.now();
|
||||
if ( this.domain === undefined ) {
|
||||
void this.getDomain();
|
||||
}
|
||||
if ( this.docDomain === undefined ) {
|
||||
void this.getDocDomain();
|
||||
}
|
||||
if ( this.tabDomain === undefined ) {
|
||||
void this.getTabDomain();
|
||||
}
|
||||
µBlock.logger.writeOne(this);
|
||||
},
|
||||
originFromURI: µBlock.URI.originFromURI,
|
||||
hostnameFromURI: µBlock.URI.hostnameFromURI,
|
||||
domainFromHostname: µBlock.URI.domainFromHostname,
|
||||
};
|
||||
|
||||
µBlock.filteringContext = new µBlock.FilteringContext();
|
@ -162,18 +162,18 @@
|
||||
};
|
||||
|
||||
const logOne = function(details, exception, selector) {
|
||||
µb.logger.writeOne(
|
||||
details.tabId,
|
||||
'cosmetic',
|
||||
{
|
||||
µBlock.filteringContext
|
||||
.duplicate()
|
||||
.fromTabId(details.tabId)
|
||||
.setRealm('cosmetic')
|
||||
.setType('dom')
|
||||
.setURL(details.url)
|
||||
.setDocOriginFromURL(details.url)
|
||||
.setFilter({
|
||||
source: 'cosmetic',
|
||||
raw: (exception === 0 ? '##' : '#@#') + '^' + selector
|
||||
},
|
||||
'dom',
|
||||
details.url,
|
||||
null,
|
||||
details.hostname
|
||||
);
|
||||
})
|
||||
.toLogger();
|
||||
};
|
||||
|
||||
const applyProceduralSelector = function(details, selector) {
|
||||
@ -192,7 +192,7 @@
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
if ( modified && µb.logger.isEnabled() ) {
|
||||
if ( modified && µb.logger.enabled ) {
|
||||
logOne(details, 0, pselector.raw);
|
||||
}
|
||||
return modified;
|
||||
@ -209,7 +209,7 @@
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
if ( modified && µb.logger.isEnabled() ) {
|
||||
if ( modified && µb.logger.enabled ) {
|
||||
logOne(details, 0, selector);
|
||||
}
|
||||
return modified;
|
||||
@ -277,7 +277,7 @@
|
||||
};
|
||||
|
||||
api.retrieve = function(details) {
|
||||
let hostname = details.hostname;
|
||||
const hostname = details.hostname;
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/2835
|
||||
// Do not filter if the site is under an `allow` rule.
|
||||
@ -288,13 +288,13 @@
|
||||
return;
|
||||
}
|
||||
|
||||
let toRemoveArray = [];
|
||||
let domainHash = µb.staticExtFilteringEngine.makeHash(details.domain);
|
||||
const toRemoveArray = [];
|
||||
const domainHash = µb.staticExtFilteringEngine.makeHash(details.domain);
|
||||
if ( domainHash !== 0 ) {
|
||||
filterDB.retrieve(domainHash, hostname, toRemoveArray);
|
||||
}
|
||||
let entity = details.entity;
|
||||
let entityHash = µb.staticExtFilteringEngine.makeHash(entity);
|
||||
const entity = details.entity;
|
||||
const entityHash = µb.staticExtFilteringEngine.makeHash(entity);
|
||||
if ( entityHash !== 0 ) {
|
||||
filterDB.retrieve(entityHash, entity, toRemoveArray);
|
||||
}
|
||||
@ -313,14 +313,14 @@
|
||||
return toRemoveArray;
|
||||
}
|
||||
|
||||
let toRemoveMap = new Map();
|
||||
for ( let entry of toRemoveArray ) {
|
||||
const toRemoveMap = new Map();
|
||||
for ( const entry of toRemoveArray ) {
|
||||
toRemoveMap.set(entry.selector, entry);
|
||||
}
|
||||
for ( let entry of notToRemoveArray ) {
|
||||
for ( const entry of notToRemoveArray ) {
|
||||
if ( toRemoveMap.has(entry.selector) === false ) { continue; }
|
||||
toRemoveMap.delete(entry.selector);
|
||||
if ( µb.logger.isEnabled() === false ) { continue; }
|
||||
if ( µb.logger.enabled === false ) { continue; }
|
||||
let selector = entry.selector;
|
||||
if ( entry.type === 65 ) {
|
||||
selector = JSON.parse(selector).raw;
|
||||
|
@ -559,16 +559,16 @@ var onMouseOver = (function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var currentTabId = function() {
|
||||
const currentTabId = function() {
|
||||
if ( showdomButton.classList.contains('active') === false ) { return 0; }
|
||||
return logger.tabIdFromPageSelector();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var injectInspector = function() {
|
||||
var tabId = currentTabId();
|
||||
if ( tabId === 0 ) { return; }
|
||||
const injectInspector = function() {
|
||||
const tabId = currentTabId();
|
||||
if ( tabId <= 0 ) { return; }
|
||||
inspectedTabId = tabId;
|
||||
messaging.send('loggerUI', {
|
||||
what: 'scriptlet',
|
||||
@ -592,7 +592,11 @@ var shutdownInspector = function() {
|
||||
/******************************************************************************/
|
||||
|
||||
var onTabIdChanged = function() {
|
||||
if ( inspectedTabId !== currentTabId() ) {
|
||||
const tabId = currentTabId();
|
||||
if ( tabId <= 0 ) {
|
||||
return toggleOff();
|
||||
}
|
||||
if ( inspectedTabId !== tabId ) {
|
||||
shutdownInspector();
|
||||
injectInspector();
|
||||
}
|
||||
@ -632,7 +636,8 @@ var revert = function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var toggleOn = function() {
|
||||
const toggleOn = function() {
|
||||
uDom.nodeFromId('inspectors').classList.add('dom');
|
||||
window.addEventListener('beforeunload', toggleOff);
|
||||
document.addEventListener('tabIdChanged', onTabIdChanged);
|
||||
domTree.addEventListener('click', onClicked, true);
|
||||
@ -647,7 +652,9 @@ var toggleOn = function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var toggleOff = function() {
|
||||
const toggleOff = function() {
|
||||
showdomButton.classList.remove('active');
|
||||
uDom.nodeFromId('inspectors').classList.remove('dom');
|
||||
shutdownInspector();
|
||||
window.removeEventListener('beforeunload', toggleOff);
|
||||
document.removeEventListener('tabIdChanged', onTabIdChanged);
|
||||
@ -663,7 +670,7 @@ var toggleOff = function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var toggle = function() {
|
||||
const toggle = function() {
|
||||
if ( showdomButton.classList.toggle('active') ) {
|
||||
toggleOn();
|
||||
} else {
|
||||
|
@ -29,16 +29,17 @@
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var logger = self.logger = {
|
||||
const messaging = vAPI.messaging;
|
||||
|
||||
const logger = self.logger = {
|
||||
ownerId: Date.now()
|
||||
};
|
||||
|
||||
var messaging = vAPI.messaging;
|
||||
var activeTabId;
|
||||
let activeTabId;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var removeAllChildren = logger.removeAllChildren = function(node) {
|
||||
const removeAllChildren = logger.removeAllChildren = function(node) {
|
||||
while ( node.firstChild ) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
@ -46,18 +47,19 @@ var removeAllChildren = logger.removeAllChildren = function(node) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var tabIdFromClassName = function(className) {
|
||||
var matches = className.match(/\btab_([^ ]+)\b/);
|
||||
const tabIdFromClassName = function(className) {
|
||||
const matches = className.match(/\btab_([^ ]+)\b/);
|
||||
if ( matches === null ) { return 0; }
|
||||
if ( matches[1] === 'bts' ) { return -1; }
|
||||
return parseInt(matches[1], 10);
|
||||
};
|
||||
|
||||
var tabIdFromPageSelector = logger.tabIdFromPageSelector = function() {
|
||||
var tabClass = uDom.nodeFromId('pageSelector').value;
|
||||
const tabIdFromPageSelector = logger.tabIdFromPageSelector = function() {
|
||||
const tabClass = uDom.nodeFromId('pageSelector').value;
|
||||
if ( tabClass === 'tab_active' && activeTabId !== undefined ) {
|
||||
return activeTabId;
|
||||
}
|
||||
if ( tabClass === 'tab_bts' ) { return -1; }
|
||||
return /^tab_\d+$/.test(tabClass) ? parseInt(tabClass.slice(4), 10) : 0;
|
||||
};
|
||||
|
||||
@ -78,12 +80,11 @@ var tabIdFromPageSelector = logger.tabIdFromPageSelector = function() {
|
||||
var tbody = document.querySelector('#netInspector tbody');
|
||||
var trJunkyard = [];
|
||||
var tdJunkyard = [];
|
||||
var firstVarDataCol = 2; // currently, column 2 (0-based index)
|
||||
var lastVarDataIndex = 4; // currently, d0-d3
|
||||
var firstVarDataCol = 1;
|
||||
var lastVarDataIndex = 6;
|
||||
var maxEntries = 5000;
|
||||
var allTabIds = new Map();
|
||||
var allTabIdsToken;
|
||||
var hiddenTemplate = document.querySelector('#hiddenTemplate > span');
|
||||
var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/;
|
||||
var netFilteringDialog = uDom.nodeFromId('netFilteringDialog');
|
||||
|
||||
@ -159,14 +160,15 @@ var renderedURLTemplate = document.querySelector('#renderedURLTemplate > span');
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var createCellAt = function(tr, index) {
|
||||
var td = tr.cells[index];
|
||||
var mustAppend = !td;
|
||||
const createCellAt = function(tr, index) {
|
||||
let td = tr.cells[index];
|
||||
const mustAppend = !td;
|
||||
if ( mustAppend ) {
|
||||
td = tdJunkyard.pop();
|
||||
}
|
||||
if ( td ) {
|
||||
td.removeAttribute('colspan');
|
||||
td.removeAttribute('title');
|
||||
td.textContent = '';
|
||||
} else {
|
||||
td = document.createElement('td');
|
||||
@ -180,24 +182,25 @@ var createCellAt = function(tr, index) {
|
||||
/******************************************************************************/
|
||||
|
||||
var createRow = function(layout) {
|
||||
var tr = trJunkyard.pop();
|
||||
let tr = trJunkyard.pop();
|
||||
if ( tr ) {
|
||||
tr.className = '';
|
||||
tr.removeAttribute('data-hn-page');
|
||||
tr.removeAttribute('data-hn-frame');
|
||||
tr.removeAttribute('data-tabhn');
|
||||
tr.removeAttribute('data-dochn');
|
||||
tr.removeAttribute('data-filter');
|
||||
tr.removeAttribute('data-tabid');
|
||||
tr.removeAttribute('title');
|
||||
} else {
|
||||
tr = document.createElement('tr');
|
||||
}
|
||||
for ( var index = 0; index < firstVarDataCol; index++ ) {
|
||||
let index = 0;
|
||||
for ( ; index < firstVarDataCol; index++ ) {
|
||||
createCellAt(tr, index);
|
||||
}
|
||||
var i = 1, span = 1, td;
|
||||
let i = 1, span = 1, td;
|
||||
for (;;) {
|
||||
td = createCellAt(tr, index);
|
||||
if ( i === lastVarDataIndex ) {
|
||||
break;
|
||||
}
|
||||
if ( i === lastVarDataIndex ) { break; }
|
||||
if ( layout.charAt(i) !== '1' ) {
|
||||
span += 1;
|
||||
} else {
|
||||
@ -221,24 +224,15 @@ var createRow = function(layout) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var createHiddenTextNode = function(text) {
|
||||
var node = hiddenTemplate.cloneNode(true);
|
||||
node.textContent = text;
|
||||
return node;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var padTo2 = function(v) {
|
||||
return v < 10 ? '0' + v : v;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var createGap = function(tabId, url) {
|
||||
var tr = createRow('1');
|
||||
tr.classList.add('tab');
|
||||
tr.classList.add('canMtx');
|
||||
const createGap = function(tabId, url) {
|
||||
const tr = createRow('1');
|
||||
tr.setAttribute('data-tabid', tabId);
|
||||
tr.classList.add('tab_' + tabId);
|
||||
tr.classList.add('maindoc');
|
||||
tr.cells[firstVarDataCol].textContent = url;
|
||||
@ -247,36 +241,30 @@ var createGap = function(tabId, url) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var renderNetLogEntry = function(tr, entry) {
|
||||
var trcl = tr.classList;
|
||||
var filter = entry.d0 || undefined;
|
||||
var type = entry.d1;
|
||||
var url = entry.d2;
|
||||
var td;
|
||||
|
||||
trcl.add('canMtx');
|
||||
var renderNetLogEntry = function(tr, details) {
|
||||
const trcl = tr.classList;
|
||||
const type = details.type;
|
||||
const url = details.url;
|
||||
let td;
|
||||
|
||||
// If the request is that of a root frame, insert a gap in the table
|
||||
// in order to visually separate entries for different documents.
|
||||
if ( type === 'main_frame' ) {
|
||||
createGap(entry.tab, url);
|
||||
createGap(details.tabId, url);
|
||||
}
|
||||
|
||||
// Contexts
|
||||
if ( entry.d3 ) {
|
||||
tr.setAttribute('data-hn-page', entry.d3);
|
||||
}
|
||||
if ( entry.d4 ) {
|
||||
tr.setAttribute('data-hn-frame', entry.d4);
|
||||
tr.classList.add('cat_' + details.realm);
|
||||
|
||||
let filter = details.filter || undefined;
|
||||
let filteringType;
|
||||
if ( filter !== undefined ) {
|
||||
if ( typeof filter.source === 'string' ) {
|
||||
filteringType = filter.source;
|
||||
trcl.add(filteringType);
|
||||
}
|
||||
}
|
||||
|
||||
var filteringType;
|
||||
if ( filter !== undefined && typeof filter.source === 'string' ) {
|
||||
filteringType = filter.source;
|
||||
trcl.add(filteringType);
|
||||
}
|
||||
|
||||
td = tr.cells[2];
|
||||
td = tr.cells[1];
|
||||
if ( filter !== undefined ) {
|
||||
if ( filteringType === 'static' ) {
|
||||
td.textContent = filter.raw;
|
||||
@ -290,7 +278,7 @@ var renderNetLogEntry = function(tr, entry) {
|
||||
}
|
||||
}
|
||||
|
||||
td = tr.cells[3];
|
||||
td = tr.cells[2];
|
||||
if ( filter !== undefined ) {
|
||||
if ( filter.result === 1 ) {
|
||||
trcl.add('blocked');
|
||||
@ -301,65 +289,86 @@ var renderNetLogEntry = function(tr, entry) {
|
||||
} else if ( filter.result === 3 ) {
|
||||
trcl.add('nooped');
|
||||
td.textContent = '**';
|
||||
} else if ( filter.source === 'redirect' ) {
|
||||
} else if ( filteringType === 'redirect' ) {
|
||||
trcl.add('redirect');
|
||||
td.textContent = '<<';
|
||||
}
|
||||
}
|
||||
|
||||
tr.cells[4].textContent = (prettyRequestTypes[type] || type);
|
||||
if ( details.tabHostname ) {
|
||||
tr.setAttribute('data-tabhn', details.tabHostname);
|
||||
}
|
||||
if ( details.docHostname ) {
|
||||
tr.setAttribute('data-dochn', details.docHostname);
|
||||
tr.cells[3].textContent = details.docHostname;
|
||||
}
|
||||
|
||||
var re = null;
|
||||
// Partyness
|
||||
if ( details.realm === 'net' && details.domain !== undefined ) {
|
||||
td = tr.cells[4];
|
||||
let text = '';
|
||||
if ( details.tabDomain !== undefined ) {
|
||||
text += details.domain === details.tabDomain ? '1' : '3';
|
||||
} else {
|
||||
text += '?';
|
||||
}
|
||||
if ( details.docDomain !== details.tabDomain ) {
|
||||
text += ',';
|
||||
if ( details.docDomain !== undefined ) {
|
||||
text += details.domain === details.docDomain ? '1' : '3';
|
||||
} else {
|
||||
text += '?';
|
||||
}
|
||||
}
|
||||
td.textContent = text;
|
||||
text = details.domain;
|
||||
if ( details.docDomain ) {
|
||||
text = details.docDomain + ' \u21d2 ' + text;
|
||||
}
|
||||
if ( details.tabDomain && details.tabDomain !== details.docDomain ) {
|
||||
text = details.tabDomain + ' \u21d2 ' + text;
|
||||
}
|
||||
td.setAttribute('title', text);
|
||||
}
|
||||
|
||||
tr.cells[5].textContent = (prettyRequestTypes[type] || type);
|
||||
|
||||
let re = null;
|
||||
if ( filteringType === 'static' ) {
|
||||
re = new RegExp(filter.regex, 'gi');
|
||||
} else if ( filteringType === 'dynamicUrl' ) {
|
||||
re = regexFromURLFilteringResult(filter.rule.join(' '));
|
||||
}
|
||||
tr.cells[5].appendChild(nodeFromURL(url, re));
|
||||
tr.cells[6].appendChild(nodeFromURL(url, re));
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var renderLogEntry = function(entry) {
|
||||
var tr;
|
||||
var fvdc = firstVarDataCol;
|
||||
var renderLogEntry = function(details) {
|
||||
const fvdc = firstVarDataCol;
|
||||
let tr;
|
||||
|
||||
switch ( entry.cat ) {
|
||||
case 'error':
|
||||
case 'info':
|
||||
if ( details.error !== undefined ) {
|
||||
tr = createRow('1');
|
||||
tr.cells[fvdc].textContent = entry.d0;
|
||||
break;
|
||||
|
||||
case 'cosmetic':
|
||||
case 'net':
|
||||
case 'redirect':
|
||||
tr = createRow('1111');
|
||||
renderNetLogEntry(tr, entry);
|
||||
break;
|
||||
|
||||
default:
|
||||
tr.cells[fvdc].textContent = details.error;
|
||||
} else if ( details.url !== undefined ) {
|
||||
tr = createRow('111111');
|
||||
renderNetLogEntry(tr, details);
|
||||
} else {
|
||||
tr = createRow('1');
|
||||
tr.cells[fvdc].textContent = entry.d0;
|
||||
break;
|
||||
tr.cells[fvdc].textContent = '???';
|
||||
}
|
||||
|
||||
// Fields common to all rows.
|
||||
var time = logDate;
|
||||
time.setTime(entry.tstamp - logDateTimezoneOffset);
|
||||
const time = logDate;
|
||||
time.setTime(details.tstamp - logDateTimezoneOffset);
|
||||
tr.cells[0].textContent = padTo2(time.getUTCHours()) + ':' +
|
||||
padTo2(time.getUTCMinutes()) + ':' +
|
||||
padTo2(time.getSeconds());
|
||||
|
||||
if ( entry.tab ) {
|
||||
tr.classList.add('tab');
|
||||
tr.classList.add(classNameFromTabId(entry.tab));
|
||||
if ( entry.tab < 0 ) {
|
||||
tr.cells[1].appendChild(createHiddenTextNode('bts'));
|
||||
}
|
||||
}
|
||||
if ( entry.cat !== '' ) {
|
||||
tr.classList.add('cat_' + entry.cat);
|
||||
if ( details.tabId ) {
|
||||
tr.setAttribute('data-tabid', details.tabId);
|
||||
tr.classList.add(classNameFromTabId(details.tabId));
|
||||
}
|
||||
|
||||
rowFilterer.filterOne(tr, true);
|
||||
@ -368,29 +377,29 @@ var renderLogEntry = function(entry) {
|
||||
};
|
||||
|
||||
// Reuse date objects.
|
||||
var logDate = new Date(),
|
||||
logDateTimezoneOffset = logDate.getTimezoneOffset() * 60000;
|
||||
const logDate = new Date();
|
||||
const logDateTimezoneOffset = logDate.getTimezoneOffset() * 60000;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var renderLogEntries = function(response) {
|
||||
const renderLogEntries = function(response) {
|
||||
document.body.classList.toggle('colorBlind', response.colorBlind);
|
||||
|
||||
let entries = response.entries;
|
||||
const entries = response.entries;
|
||||
if ( entries.length === 0 ) { return; }
|
||||
|
||||
// Preserve scroll position
|
||||
let height = tbody.offsetHeight;
|
||||
const height = tbody.offsetHeight;
|
||||
|
||||
let tabIds = allTabIds;
|
||||
for ( let i = 0, n = entries.length; i < n; i++ ) {
|
||||
let entry = entries[i];
|
||||
let tr = renderLogEntry(entries[i]);
|
||||
const tabIds = allTabIds;
|
||||
for ( const entry of entries ) {
|
||||
const details = JSON.parse(entry.details);
|
||||
const tr = renderLogEntry(details);
|
||||
// https://github.com/gorhill/uBlock/issues/1613#issuecomment-217637122
|
||||
// Unlikely, but it may happen: mark as void if associated tab no
|
||||
// longer exist.
|
||||
if ( entry.tab && tabIds.has(entry.tab) === false ) {
|
||||
tr.classList.remove('canMtx');
|
||||
if ( details.tabId && tabIds.has(details.tabId) === false ) {
|
||||
tr.classList.add('void');
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,9 +409,9 @@ var renderLogEntries = function(response) {
|
||||
truncateLog(maxEntries);
|
||||
|
||||
// Follow waterfall if not observing top of waterfall.
|
||||
let yDelta = tbody.offsetHeight - height;
|
||||
const yDelta = tbody.offsetHeight - height;
|
||||
if ( yDelta === 0 ) { return; }
|
||||
let container = uDom.nodeFromSelector('#netInspector .vscrollable');
|
||||
const container = uDom.nodeFromSelector('#netInspector .vscrollable');
|
||||
if ( container.scrollTop !== 0 ) {
|
||||
container.scrollTop += yDelta;
|
||||
}
|
||||
@ -428,21 +437,20 @@ let updateCurrentTabTitle = (function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var synchronizeTabIds = function(newTabIds) {
|
||||
var select = uDom.nodeFromId('pageSelector');
|
||||
var selectValue = select.value;
|
||||
|
||||
var oldTabIds = allTabIds;
|
||||
var autoDeleteVoidRows = selectValue === 'tab_active';
|
||||
var rowVoided = false;
|
||||
for ( var tabId of oldTabIds.keys() ) {
|
||||
const synchronizeTabIds = function(newTabIds) {
|
||||
const select = uDom.nodeFromId('pageSelector');
|
||||
const selectValue = select.value;
|
||||
const oldTabIds = allTabIds;
|
||||
const autoDeleteVoidRows = selectValue === 'tab_active';
|
||||
let rowVoided = false;
|
||||
for ( const tabId of oldTabIds.keys() ) {
|
||||
if ( newTabIds.has(tabId) ) { continue; }
|
||||
// Mark or remove voided rows
|
||||
var trs = uDom('.tab_' + tabId);
|
||||
const trs = uDom('.tab_' + tabId);
|
||||
if ( autoDeleteVoidRows ) {
|
||||
toJunkyard(trs);
|
||||
} else {
|
||||
trs.removeClass('canMtx');
|
||||
trs.addClass('void');
|
||||
rowVoided = true;
|
||||
}
|
||||
// Remove popup if it is currently bound to a removed tab.
|
||||
@ -451,14 +459,14 @@ var synchronizeTabIds = function(newTabIds) {
|
||||
}
|
||||
}
|
||||
|
||||
var tabIds = Array.from(newTabIds.keys()).sort(function(a, b) {
|
||||
const tabIds = Array.from(newTabIds.keys()).sort(function(a, b) {
|
||||
return newTabIds.get(a).localeCompare(newTabIds.get(b));
|
||||
});
|
||||
var option;
|
||||
for ( var i = 0, j = 3; i < tabIds.length; i++ ) {
|
||||
tabId = tabIds[i];
|
||||
let j = 3;
|
||||
for ( let i = 0; i < tabIds.length; i++ ) {
|
||||
const tabId = tabIds[i];
|
||||
if ( tabId < 0 ) { continue; }
|
||||
option = select.options[j];
|
||||
let option = select.options[j];
|
||||
if ( !option ) {
|
||||
option = document.createElement('option');
|
||||
select.appendChild(option);
|
||||
@ -508,7 +516,7 @@ var truncateLog = function(size) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onLogBufferRead = function(response) {
|
||||
const onLogBufferRead = function(response) {
|
||||
if ( !response || response.unavailable ) {
|
||||
readLogBufferAsync();
|
||||
return;
|
||||
@ -547,7 +555,7 @@ var onLogBufferRead = function(response) {
|
||||
if ( rowVoided ) {
|
||||
uDom('#clean').toggleClass(
|
||||
'disabled',
|
||||
tbody.querySelector('#netInspector tr.tab:not(.canMtx)') === null
|
||||
tbody.querySelector('#netInspector tr[data-tabid].void') === null
|
||||
);
|
||||
}
|
||||
|
||||
@ -566,20 +574,20 @@ var onLogBufferRead = function(response) {
|
||||
// automatically. If called after init time, this will be messy, and this would
|
||||
// require a bit more code to ensure no multi time out events.
|
||||
|
||||
var readLogBuffer = function() {
|
||||
const readLogBuffer = function() {
|
||||
if ( logger.ownerId === undefined ) { return; }
|
||||
vAPI.messaging.send(
|
||||
'loggerUI',
|
||||
{
|
||||
what: 'readAll',
|
||||
ownerId: logger.ownerId,
|
||||
tabIdsToken: allTabIdsToken
|
||||
tabIdsToken: allTabIdsToken,
|
||||
},
|
||||
onLogBufferRead
|
||||
);
|
||||
};
|
||||
|
||||
var readLogBufferAsync = function() {
|
||||
const readLogBufferAsync = function() {
|
||||
if ( logger.ownerId === undefined ) { return; }
|
||||
vAPI.setTimeout(readLogBuffer, 1200);
|
||||
};
|
||||
@ -646,10 +654,14 @@ let pageSelectorFromURLHash = (function() {
|
||||
select.selectedIndex = option.index;
|
||||
select.value = option.value;
|
||||
|
||||
uDom('.needtab').toggleClass(
|
||||
uDom('.needdom').toggleClass(
|
||||
'disabled',
|
||||
tabClass === '' || tabClass === 'tab_bts'
|
||||
);
|
||||
uDom('.needscope').toggleClass(
|
||||
'disabled',
|
||||
tabClass === ''
|
||||
);
|
||||
};
|
||||
})();
|
||||
|
||||
@ -657,7 +669,7 @@ let pageSelectorFromURLHash = (function() {
|
||||
|
||||
var reloadTab = function(ev) {
|
||||
var tabId = tabIdFromPageSelector();
|
||||
if ( tabId === 0 ) { return; }
|
||||
if ( tabId <= 0 ) { return; }
|
||||
messaging.send('loggerUI', {
|
||||
what: 'reloadTab',
|
||||
tabId: tabId,
|
||||
@ -1227,10 +1239,10 @@ var netFilteringManager = (function() {
|
||||
dialog = netFilteringDialog.querySelector('.dialog');
|
||||
targetRow = ev.target.parentElement;
|
||||
targetTabId = tabIdFromClassName(targetRow.className);
|
||||
targetType = targetRow.cells[4].textContent.trim() || '';
|
||||
targetURLs = createTargetURLs(targetRow.cells[5].textContent);
|
||||
targetPageHostname = targetRow.getAttribute('data-hn-page') || '';
|
||||
targetFrameHostname = targetRow.getAttribute('data-hn-frame') || '';
|
||||
targetType = targetRow.cells[5].textContent.trim() || '';
|
||||
targetURLs = createTargetURLs(targetRow.cells[6].textContent);
|
||||
targetPageHostname = targetRow.getAttribute('data-tabhn') || '';
|
||||
targetFrameHostname = targetRow.getAttribute('data-dochn') || '';
|
||||
|
||||
// We need the root domain names for best user experience.
|
||||
messaging.send(
|
||||
@ -1345,7 +1357,7 @@ var reverseLookupManager = (function() {
|
||||
|
||||
let toggleOn = function(ev) {
|
||||
let row = ev.target.parentElement;
|
||||
rawFilter = row.cells[2].textContent;
|
||||
rawFilter = row.cells[1].textContent;
|
||||
if ( rawFilter === '' ) { return; }
|
||||
|
||||
if ( row.classList.contains('cat_net') ) {
|
||||
@ -1363,7 +1375,7 @@ var reverseLookupManager = (function() {
|
||||
'loggerUI',
|
||||
{
|
||||
what: 'listsFromCosmeticFilter',
|
||||
url: row.cells[5].textContent,
|
||||
url: row.cells[6].textContent,
|
||||
rawFilter: rawFilter,
|
||||
},
|
||||
reverseLookupDone
|
||||
@ -1385,10 +1397,10 @@ var reverseLookupManager = (function() {
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
var rowFilterer = (function() {
|
||||
var filters = [];
|
||||
const rowFilterer = (function() {
|
||||
let filters = [];
|
||||
|
||||
var parseInput = function() {
|
||||
const parseInput = function() {
|
||||
filters = [];
|
||||
|
||||
var rawPart, hardBeg, hardEnd;
|
||||
@ -1438,33 +1450,30 @@ var rowFilterer = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
var filterOne = function(tr, clean) {
|
||||
var ff = filters;
|
||||
var fcount = ff.length;
|
||||
const filterOne = function(tr, clean) {
|
||||
const ff = filters;
|
||||
const fcount = ff.length;
|
||||
if ( fcount === 0 && clean === true ) {
|
||||
return;
|
||||
}
|
||||
// do not filter out doc boundaries, they help separate important
|
||||
// section of log.
|
||||
var cl = tr.classList;
|
||||
if ( cl.contains('maindoc') ) {
|
||||
return;
|
||||
}
|
||||
const cl = tr.classList;
|
||||
if ( cl.contains('maindoc') ) { return; }
|
||||
if ( fcount === 0 ) {
|
||||
cl.remove('f');
|
||||
return;
|
||||
}
|
||||
var cc = tr.cells;
|
||||
var ccount = cc.length;
|
||||
var hit, j, f;
|
||||
const cc = tr.cells;
|
||||
const ccount = cc.length;
|
||||
// each filter expression must hit (implicit and-op)
|
||||
// if...
|
||||
// positive filter expression = there must one hit on any field
|
||||
// negative filter expression = there must be no hit on all fields
|
||||
for ( var i = 0; i < fcount; i++ ) {
|
||||
f = ff[i];
|
||||
hit = !f.r;
|
||||
for ( j = 0; j < ccount; j++ ) {
|
||||
for ( let i = 0; i < fcount; i++ ) {
|
||||
let f = ff[i];
|
||||
let hit = !f.r;
|
||||
for ( let j = 1; j < ccount; j++ ) {
|
||||
if ( f.re.test(cc[j].textContent) ) {
|
||||
hit = f.r;
|
||||
break;
|
||||
@ -1478,7 +1487,7 @@ var rowFilterer = (function() {
|
||||
cl.remove('f');
|
||||
};
|
||||
|
||||
var filterAll = function() {
|
||||
const filterAll = function() {
|
||||
// Special case: no filter
|
||||
if ( filters.length === 0 ) {
|
||||
uDom('#netInspector tr').removeClass('f');
|
||||
@ -1492,7 +1501,7 @@ var rowFilterer = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
var onFilterChangedAsync = (function() {
|
||||
const onFilterChangedAsync = (function() {
|
||||
var timer = null;
|
||||
var commit = function() {
|
||||
timer = null;
|
||||
@ -1507,7 +1516,7 @@ var rowFilterer = (function() {
|
||||
};
|
||||
})();
|
||||
|
||||
var onFilterButton = function() {
|
||||
const onFilterButton = function() {
|
||||
uDom.nodeFromId('netInspector').classList.toggle('f');
|
||||
};
|
||||
|
||||
@ -1559,14 +1568,14 @@ var clearBuffer = function() {
|
||||
);
|
||||
uDom.nodeFromId('clean').classList.toggle(
|
||||
'disabled',
|
||||
tbody.querySelector('#netInspector tr.tab:not(.canMtx)') === null
|
||||
tbody.querySelector('#netInspector tr[data-tabid].void') === null
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var cleanBuffer = function() {
|
||||
var rows = uDom('#netInspector tr.tab:not(.canMtx)').remove();
|
||||
var rows = uDom('#netInspector tr[data-tabid].void').remove();
|
||||
var i = rows.length;
|
||||
while ( i-- ) {
|
||||
trJunkyard.push(rows.nodeAt(i));
|
||||
@ -1587,44 +1596,23 @@ var toggleVCompactRow = function(ev) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var toggleInspectors = function() {
|
||||
uDom.nodeFromId('inspectors').classList.toggle('dom');
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var popupManager = (function() {
|
||||
var realTabId = null;
|
||||
var localTabId = null;
|
||||
var container = null;
|
||||
var popup = null;
|
||||
var popupObserver = null;
|
||||
var style = null;
|
||||
var styleTemplate = [
|
||||
'#netInspector tr:not(.tab_{{tabId}}) {',
|
||||
'cursor: not-allowed;',
|
||||
'opacity: 0.2;',
|
||||
'}'
|
||||
].join('\n');
|
||||
let realTabId = 0;
|
||||
let popup = null;
|
||||
let popupObserver = null;
|
||||
|
||||
var resizePopup = function() {
|
||||
if ( popup === null ) {
|
||||
return;
|
||||
}
|
||||
var popupBody = popup.contentWindow.document.body;
|
||||
if ( popupBody.clientWidth !== 0 && container.clientWidth !== popupBody.clientWidth ) {
|
||||
container.style.setProperty('width', popupBody.clientWidth + 'px');
|
||||
const resizePopup = function() {
|
||||
if ( popup === null ) { return; }
|
||||
const popupBody = popup.contentWindow.document.body;
|
||||
if ( popupBody.clientWidth !== 0 && popup.clientWidth !== popupBody.clientWidth ) {
|
||||
popup.style.setProperty('width', popupBody.clientWidth + 'px');
|
||||
}
|
||||
if ( popupBody.clientHeight !== 0 && popup.clientHeight !== popupBody.clientHeight ) {
|
||||
popup.style.setProperty('height', popupBody.clientHeight + 'px');
|
||||
}
|
||||
};
|
||||
|
||||
var toggleSize = function() {
|
||||
container.classList.toggle('hide');
|
||||
};
|
||||
|
||||
var onLoad = function() {
|
||||
const onLoad = function() {
|
||||
resizePopup();
|
||||
popupObserver.observe(popup.contentDocument.body, {
|
||||
subtree: true,
|
||||
@ -1632,61 +1620,55 @@ var popupManager = (function() {
|
||||
});
|
||||
};
|
||||
|
||||
var toggleOn = function(td) {
|
||||
var tr = td.parentNode;
|
||||
realTabId = localTabId = tabIdFromClassName(tr.className);
|
||||
if ( realTabId === 0 ) { return; }
|
||||
|
||||
container = uDom.nodeFromId('popupContainer');
|
||||
|
||||
container.querySelector('div > span:nth-of-type(1)').addEventListener('click', toggleSize);
|
||||
container.querySelector('div > span:nth-of-type(2)').addEventListener('click', toggleOff);
|
||||
|
||||
popup = document.createElement('iframe');
|
||||
popup.addEventListener('load', onLoad);
|
||||
popup.setAttribute('src', 'popup.html?tabId=' + realTabId);
|
||||
popupObserver = new MutationObserver(resizePopup);
|
||||
container.appendChild(popup);
|
||||
|
||||
style = uDom.nodeFromId('popupFilterer');
|
||||
style.textContent = styleTemplate.replace('{{tabId}}', localTabId);
|
||||
|
||||
var parent = uDom.nodeFromId('netInspector');
|
||||
var rect = parent.getBoundingClientRect();
|
||||
container.style.setProperty('top', rect.top + 'px');
|
||||
container.style.setProperty('right', (rect.right - parent.clientWidth) + 'px');
|
||||
parent.classList.add('popupOn');
|
||||
const setTabId = function(tabId) {
|
||||
if ( popup === null ) { return; }
|
||||
popup.setAttribute('src', 'popup.html?tabId=' + tabId);
|
||||
};
|
||||
|
||||
var toggleOff = function() {
|
||||
uDom.nodeFromId('netInspector').classList.remove('popupOn');
|
||||
const onTabIdChanged = function() {
|
||||
const tabId = tabIdFromPageSelector();
|
||||
if ( tabId === 0 ) { return toggleOff(); }
|
||||
realTabId = tabId;
|
||||
setTabId(realTabId);
|
||||
};
|
||||
|
||||
container.querySelector('div > span:nth-of-type(1)').removeEventListener('click', toggleSize);
|
||||
container.querySelector('div > span:nth-of-type(2)').removeEventListener('click', toggleOff);
|
||||
container.classList.remove('hide');
|
||||
const toggleOn = function() {
|
||||
const tabId = tabIdFromPageSelector();
|
||||
if ( tabId === 0 ) { return; }
|
||||
realTabId = tabId;
|
||||
|
||||
popup = uDom.nodeFromId('popupContainer');
|
||||
|
||||
popup.addEventListener('load', onLoad);
|
||||
popupObserver = new MutationObserver(resizePopup);
|
||||
|
||||
const parent = uDom.nodeFromId('inspectors');
|
||||
const rect = parent.getBoundingClientRect();
|
||||
popup.style.setProperty('right', (rect.right - parent.clientWidth) + 'px');
|
||||
parent.classList.add('popupOn');
|
||||
|
||||
document.addEventListener('tabIdChanged', onTabIdChanged);
|
||||
|
||||
setTabId(realTabId);
|
||||
};
|
||||
|
||||
const toggleOff = function() {
|
||||
document.removeEventListener('tabIdChanged', onTabIdChanged);
|
||||
uDom.nodeFromId('inspectors').classList.remove('popupOn');
|
||||
popup.removeEventListener('load', onLoad);
|
||||
popupObserver.disconnect();
|
||||
popupObserver = null;
|
||||
popup.setAttribute('src', '');
|
||||
container.removeChild(popup);
|
||||
popup = null;
|
||||
|
||||
style.textContent = '';
|
||||
style = null;
|
||||
|
||||
container = null;
|
||||
realTabId = null;
|
||||
|
||||
realTabId = 0;
|
||||
};
|
||||
|
||||
var exports = {
|
||||
toggleOn: function(ev) {
|
||||
if ( realTabId === null ) {
|
||||
toggleOn(ev.target);
|
||||
}
|
||||
const exports = {
|
||||
toggleOn: function() {
|
||||
void (realTabId === 0 ? toggleOn() : toggleOff());
|
||||
},
|
||||
toggleOff: function() {
|
||||
if ( realTabId !== null ) {
|
||||
if ( realTabId !== 0 ) {
|
||||
toggleOff();
|
||||
}
|
||||
}
|
||||
@ -1701,14 +1683,14 @@ var popupManager = (function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var grabView = function() {
|
||||
const grabView = function() {
|
||||
if ( logger.ownerId === undefined ) {
|
||||
logger.ownerId = Date.now();
|
||||
}
|
||||
readLogBufferAsync();
|
||||
};
|
||||
|
||||
var releaseView = function() {
|
||||
const releaseView = function() {
|
||||
if ( logger.ownerId === undefined ) { return; }
|
||||
vAPI.messaging.send(
|
||||
'loggerUI',
|
||||
@ -1728,16 +1710,15 @@ readLogBuffer();
|
||||
|
||||
uDom('#pageSelector').on('change', pageSelectorChanged);
|
||||
uDom('#refresh').on('click', reloadTab);
|
||||
uDom('#showdom').on('click', toggleInspectors);
|
||||
uDom('#showpopup').on('click', popupManager.toggleOn);
|
||||
|
||||
uDom('#netInspector .vCompactToggler').on('click', toggleVCompactView);
|
||||
uDom('#clean').on('click', cleanBuffer);
|
||||
uDom('#clear').on('click', clearBuffer);
|
||||
uDom('#maxEntries').on('change', onMaxEntriesChanged);
|
||||
uDom('#netInspector table').on('click', 'tr > td:nth-of-type(1)', toggleVCompactRow);
|
||||
uDom('#netInspector table').on('click', 'tr.canMtx > td:nth-of-type(2)', popupManager.toggleOn);
|
||||
uDom('#netInspector').on('click', 'tr.canLookup > td:nth-of-type(3)', reverseLookupManager.toggleOn);
|
||||
uDom('#netInspector').on('click', 'tr.cat_net > td:nth-of-type(4)', netFilteringManager.toggleOn);
|
||||
uDom('#netInspector').on('click', 'tr.canLookup > td:nth-of-type(2)', reverseLookupManager.toggleOn);
|
||||
uDom('#netInspector').on('click', 'tr.cat_net > td:nth-of-type(3)', netFilteringManager.toggleOn);
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/507
|
||||
// Ensure tab selector is in sync with URL hash
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
|
||||
uBlock - a browser extension to block requests.
|
||||
Copyright (C) 2015-2017 Raymond Hill
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-present 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
|
||||
@ -26,34 +26,28 @@
|
||||
|
||||
µBlock.logger = (function() {
|
||||
|
||||
var LogEntry = function(args) {
|
||||
this.init(args);
|
||||
const LogEntry = function(details) {
|
||||
this.init(details);
|
||||
};
|
||||
|
||||
LogEntry.prototype.init = function(args) {
|
||||
this.tstamp = Date.now();
|
||||
this.tab = args[0] || '';
|
||||
this.cat = args[1] || '';
|
||||
this.d0 = args[2];
|
||||
this.d1 = args[3];
|
||||
this.d2 = args[4];
|
||||
this.d3 = args[5];
|
||||
this.d4 = args[6];
|
||||
LogEntry.prototype.init = function(details) {
|
||||
this.details = JSON.stringify(details);
|
||||
};
|
||||
|
||||
var buffer = null;
|
||||
var lastReadTime = 0;
|
||||
var writePtr = 0;
|
||||
let buffer = null;
|
||||
let lastReadTime = 0;
|
||||
let writePtr = 0;
|
||||
|
||||
// After 60 seconds without being read, a buffer will be considered
|
||||
// unused, and thus removed from memory.
|
||||
var logBufferObsoleteAfter = 30 * 1000;
|
||||
const logBufferObsoleteAfter = 30 * 1000;
|
||||
|
||||
var janitor = function() {
|
||||
const janitor = ( ) => {
|
||||
if (
|
||||
buffer !== null &&
|
||||
lastReadTime < (Date.now() - logBufferObsoleteAfter)
|
||||
) {
|
||||
api.enabled = false;
|
||||
buffer = null;
|
||||
writePtr = 0;
|
||||
api.ownerId = undefined;
|
||||
@ -64,31 +58,30 @@
|
||||
}
|
||||
};
|
||||
|
||||
var api = {
|
||||
const api = {
|
||||
enabled: false,
|
||||
ownerId: undefined,
|
||||
writeOne: function() {
|
||||
writeOne: function(details) {
|
||||
if ( buffer === null ) { return; }
|
||||
if ( writePtr === buffer.length ) {
|
||||
buffer.push(new LogEntry(arguments));
|
||||
buffer.push(new LogEntry(details));
|
||||
} else {
|
||||
buffer[writePtr].init(arguments);
|
||||
buffer[writePtr].init(details);
|
||||
}
|
||||
writePtr += 1;
|
||||
},
|
||||
readAll: function(ownerId) {
|
||||
this.ownerId = ownerId;
|
||||
if ( buffer === null ) {
|
||||
this.enabled = true;
|
||||
buffer = [];
|
||||
vAPI.setTimeout(janitor, logBufferObsoleteAfter);
|
||||
}
|
||||
var out = buffer.slice(0, writePtr);
|
||||
const out = buffer.slice(0, writePtr);
|
||||
writePtr = 0;
|
||||
lastReadTime = Date.now();
|
||||
return out;
|
||||
},
|
||||
isEnabled: function() {
|
||||
return buffer !== null;
|
||||
}
|
||||
};
|
||||
|
||||
return api;
|
||||
|
@ -527,9 +527,8 @@ var onMessage = function(request, sender, callback) {
|
||||
|
||||
case 'shouldRenderNoscriptTags':
|
||||
if ( pageStore === null ) { break; }
|
||||
let tabContext = µb.tabContextManager.lookup(tabId);
|
||||
if ( tabContext === null ) { break; }
|
||||
if ( pageStore.filterScripting(tabContext.rootHostname, undefined) ) {
|
||||
const fctxt = µBlock.filteringContext.fromTabId(tabId);
|
||||
if ( pageStore.filterScripting(fctxt, undefined) ) {
|
||||
vAPI.tabs.injectScript(
|
||||
tabId,
|
||||
{
|
||||
@ -561,7 +560,10 @@ var onMessage = function(request, sender, callback) {
|
||||
request.domain = µb.URI.domainFromHostname(request.hostname);
|
||||
request.entity = µb.URI.entityFromDomain(request.domain);
|
||||
response.specificCosmeticFilters =
|
||||
µb.cosmeticFilteringEngine.retrieveSpecificSelectors(request, response);
|
||||
µb.cosmeticFilteringEngine.retrieveSpecificSelectors(
|
||||
request,
|
||||
response
|
||||
);
|
||||
if ( µb.canInjectScriptletsNow === false ) {
|
||||
response.scriptlets = µb.scriptletFilteringEngine.retrieve(request);
|
||||
}
|
||||
@ -1319,25 +1321,20 @@ var domSurveyFinalReport = function(tabId) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var logCosmeticFilters = function(tabId, details) {
|
||||
if ( µb.logger.isEnabled() === false ) {
|
||||
return;
|
||||
}
|
||||
const logCosmeticFilters = function(tabId, details) {
|
||||
if ( µb.logger.enabled === false ) { return; }
|
||||
|
||||
var selectors = details.matchedSelectors;
|
||||
|
||||
selectors.sort();
|
||||
|
||||
for ( var i = 0; i < selectors.length; i++ ) {
|
||||
µb.logger.writeOne(
|
||||
tabId,
|
||||
'cosmetic',
|
||||
{ source: 'cosmetic', raw: '##' + selectors[i] },
|
||||
'dom',
|
||||
details.frameURL,
|
||||
null,
|
||||
details.frameHostname
|
||||
);
|
||||
const filter = { source: 'cosmetic', raw: '' };
|
||||
const fctxt = µb.filteringContext.duplicate();
|
||||
fctxt.fromTabId(tabId)
|
||||
.setRealm('cosmetic')
|
||||
.setType('dom')
|
||||
.setURL(details.frameURL)
|
||||
.setDocOriginFromURL(details.frameURL)
|
||||
.setFilter(filter);
|
||||
for ( const selector of details.matchedSelectors.sort() ) {
|
||||
filter.raw = '##' + selector;
|
||||
fctxt.toLogger();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -37,18 +37,18 @@ To create a log of net requests
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var µb = µBlock;
|
||||
const µb = µBlock;
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// To mitigate memory churning
|
||||
var netFilteringCacheJunkyard = [],
|
||||
netFilteringCacheJunkyardMax = 10;
|
||||
const netFilteringCacheJunkyard = [];
|
||||
const netFilteringCacheJunkyardMax = 10;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var NetFilteringResultCache = function() {
|
||||
const NetFilteringResultCache = function() {
|
||||
this.boundPruneAsyncCallback = this.pruneAsyncCallback.bind(this);
|
||||
this.init();
|
||||
};
|
||||
@ -60,7 +60,7 @@ NetFilteringResultCache.prototype.shelfLife = 15 * 1000;
|
||||
/******************************************************************************/
|
||||
|
||||
NetFilteringResultCache.factory = function() {
|
||||
var entry = netFilteringCacheJunkyard.pop();
|
||||
let entry = netFilteringCacheJunkyard.pop();
|
||||
if ( entry === undefined ) {
|
||||
entry = new NetFilteringResultCache();
|
||||
} else {
|
||||
@ -90,31 +90,35 @@ NetFilteringResultCache.prototype.dispose = function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
NetFilteringResultCache.prototype.rememberResult = function(context, result, logData) {
|
||||
NetFilteringResultCache.prototype.rememberResult = function(
|
||||
fctxt,
|
||||
result,
|
||||
logData
|
||||
) {
|
||||
if ( this.results.size === 0 ) {
|
||||
this.pruneAsync();
|
||||
}
|
||||
var key = context.pageHostname + ' ' + context.requestType + ' ' + context.requestURL;
|
||||
const key = fctxt.getDocHostname() + ' ' + fctxt.type + ' ' + fctxt.url;
|
||||
this.results.set(key, {
|
||||
result: result,
|
||||
logData: logData,
|
||||
tstamp: Date.now()
|
||||
});
|
||||
if ( result !== 1 ) { return; }
|
||||
var now = Date.now();
|
||||
const now = Date.now();
|
||||
this.blocked.set(key, now);
|
||||
this.hash = now;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
NetFilteringResultCache.prototype.rememberBlock = function(details) {
|
||||
NetFilteringResultCache.prototype.rememberBlock = function(fctxt) {
|
||||
if ( this.blocked.size === 0 ) {
|
||||
this.pruneAsync();
|
||||
}
|
||||
var now = Date.now();
|
||||
const now = Date.now();
|
||||
this.blocked.set(
|
||||
details.pageHostname + ' ' + details.requestType + ' ' + details.requestURL,
|
||||
fctxt.getDocHostname() + ' ' + fctxt.type + ' ' + fctxt.url,
|
||||
now
|
||||
);
|
||||
this.hash = now;
|
||||
@ -162,21 +166,20 @@ NetFilteringResultCache.prototype.pruneAsyncCallback = function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
NetFilteringResultCache.prototype.lookupResult = function(context) {
|
||||
NetFilteringResultCache.prototype.lookupResult = function(fctxt) {
|
||||
return this.results.get(
|
||||
context.pageHostname + ' ' +
|
||||
context.requestType + ' ' +
|
||||
context.requestURL
|
||||
fctxt.getDocHostname() + ' ' +
|
||||
fctxt.type + ' ' +
|
||||
fctxt.url
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
NetFilteringResultCache.prototype.lookupAllBlocked = function(hostname) {
|
||||
var result = [],
|
||||
pos;
|
||||
for ( var entry of this.blocked ) {
|
||||
pos = entry[0].indexOf(' ');
|
||||
const result = [];
|
||||
for ( const entry of this.blocked ) {
|
||||
const pos = entry[0].indexOf(' ');
|
||||
if ( entry[0].slice(0, pos) === hostname ) {
|
||||
result[result.length] = entry[0].slice(pos + 1);
|
||||
}
|
||||
@ -193,19 +196,19 @@ NetFilteringResultCache.prototype.lookupAllBlocked = function(hostname) {
|
||||
// refactoring.
|
||||
|
||||
// To mitigate memory churning
|
||||
var frameStoreJunkyard = [];
|
||||
var frameStoreJunkyardMax = 50;
|
||||
const frameStoreJunkyard = [];
|
||||
const frameStoreJunkyardMax = 50;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var FrameStore = function(frameURL) {
|
||||
const FrameStore = function(frameURL) {
|
||||
this.init(frameURL);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
FrameStore.factory = function(frameURL) {
|
||||
var entry = frameStoreJunkyard.pop();
|
||||
const entry = frameStoreJunkyard.pop();
|
||||
if ( entry === undefined ) {
|
||||
return new FrameStore(frameURL);
|
||||
}
|
||||
@ -215,7 +218,7 @@ FrameStore.factory = function(frameURL) {
|
||||
/******************************************************************************/
|
||||
|
||||
FrameStore.prototype.init = function(frameURL) {
|
||||
var µburi = µb.URI;
|
||||
const µburi = µb.URI;
|
||||
this.pageHostname = µburi.hostnameFromURI(frameURL);
|
||||
this.pageDomain = µburi.domainFromHostname(this.pageHostname) || this.pageHostname;
|
||||
return this;
|
||||
@ -235,12 +238,12 @@ FrameStore.prototype.dispose = function() {
|
||||
/******************************************************************************/
|
||||
|
||||
// To mitigate memory churning
|
||||
var pageStoreJunkyard = [];
|
||||
var pageStoreJunkyardMax = 10;
|
||||
const pageStoreJunkyard = [];
|
||||
const pageStoreJunkyardMax = 10;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var PageStore = function(tabId, context) {
|
||||
const PageStore = function(tabId, context) {
|
||||
this.init(tabId, context);
|
||||
this.journal = [];
|
||||
this.journalTimer = null;
|
||||
@ -251,7 +254,7 @@ var PageStore = function(tabId, context) {
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.factory = function(tabId, context) {
|
||||
var entry = pageStoreJunkyard.pop();
|
||||
let entry = pageStoreJunkyard.pop();
|
||||
if ( entry === undefined ) {
|
||||
entry = new PageStore(tabId, context);
|
||||
} else {
|
||||
@ -297,6 +300,18 @@ PageStore.prototype.init = function(tabId, context) {
|
||||
this.netFilteringCache = NetFilteringResultCache.factory();
|
||||
this.internalRedirectionCount = 0;
|
||||
|
||||
// The current filtering context is cloned because:
|
||||
// - We may be called with or without the current context having been
|
||||
// initialized.
|
||||
// - If it has been initialized, we do not want to change the state
|
||||
// of the current context.
|
||||
const fctxt = µb.logger.enabled
|
||||
? µBlock.filteringContext
|
||||
.duplicate()
|
||||
.fromTabId(tabId)
|
||||
.setURL(tabContext.rawURL)
|
||||
: undefined;
|
||||
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/314
|
||||
const masterSwitch = tabContext.getNetFilteringSwitch();
|
||||
|
||||
@ -307,18 +322,13 @@ PageStore.prototype.init = function(tabId, context) {
|
||||
if (
|
||||
masterSwitch &&
|
||||
this.noCosmeticFiltering &&
|
||||
µb.logger.isEnabled() &&
|
||||
µb.logger.enabled &&
|
||||
context === 'tabCommitted'
|
||||
) {
|
||||
µb.logger.writeOne(
|
||||
tabId,
|
||||
'cosmetic',
|
||||
µb.sessionSwitches.toLogData(),
|
||||
'dom',
|
||||
tabContext.rawURL,
|
||||
this.tabHostname,
|
||||
this.tabHostname
|
||||
);
|
||||
fctxt.setRealm('cosmetic')
|
||||
.setType('dom')
|
||||
.setFilter(µb.sessionSwitches.toLogData())
|
||||
.toLogger();
|
||||
}
|
||||
|
||||
// Support `generichide` filter option.
|
||||
@ -332,18 +342,13 @@ PageStore.prototype.init = function(tabId, context) {
|
||||
this.noGenericCosmeticFiltering = result === 2;
|
||||
if (
|
||||
result !== 0 &&
|
||||
µb.logger.isEnabled() &&
|
||||
µb.logger.enabled &&
|
||||
context === 'tabCommitted'
|
||||
) {
|
||||
µb.logger.writeOne(
|
||||
tabId,
|
||||
'net',
|
||||
µb.staticNetFilteringEngine.toLogData(),
|
||||
'generichide',
|
||||
tabContext.rawURL,
|
||||
this.tabHostname,
|
||||
this.tabHostname
|
||||
);
|
||||
fctxt.setRealm('net')
|
||||
.setType('generichide')
|
||||
.setFilter(µb.staticNetFilteringEngine.toLogData())
|
||||
.toLogger();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -357,7 +362,7 @@ PageStore.prototype.reuse = function(context) {
|
||||
// When force refreshing a page, the page store data needs to be reset.
|
||||
|
||||
// If the hostname changes, we can't merely just update the context.
|
||||
var tabContext = µb.tabContextManager.mustLookup(this.tabId);
|
||||
const tabContext = µb.tabContextManager.mustLookup(this.tabId);
|
||||
if ( tabContext.rootHostname !== this.tabHostname ) {
|
||||
context = '';
|
||||
}
|
||||
@ -416,22 +421,18 @@ PageStore.prototype.dispose = function() {
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.disposeFrameStores = function() {
|
||||
for ( var frameStore of this.frames.values() ) {
|
||||
for ( const frameStore of this.frames.values() ) {
|
||||
frameStore.dispose();
|
||||
}
|
||||
this.frames.clear();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.getFrame = function(frameId) {
|
||||
return this.frames.get(frameId) || null;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.setFrame = function(frameId, frameURL) {
|
||||
var frameStore = this.frames.get(frameId);
|
||||
const frameStore = this.frames.get(frameId);
|
||||
if ( frameStore !== undefined ) {
|
||||
frameStore.init(frameURL);
|
||||
} else {
|
||||
@ -441,54 +442,19 @@ PageStore.prototype.setFrame = function(frameId, frameURL) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.createContextFromPage = function() {
|
||||
var context = µb.tabContextManager.createContext(this.tabId);
|
||||
context.pageHostname = context.rootHostname;
|
||||
context.pageDomain = context.rootDomain;
|
||||
return context;
|
||||
};
|
||||
|
||||
PageStore.prototype.createContextFromFrameId = function(frameId) {
|
||||
var context = µb.tabContextManager.createContext(this.tabId);
|
||||
var frameStore = this.frames.get(frameId);
|
||||
if ( frameStore !== undefined ) {
|
||||
context.pageHostname = frameStore.pageHostname;
|
||||
context.pageDomain = frameStore.pageDomain;
|
||||
} else {
|
||||
context.pageHostname = context.rootHostname;
|
||||
context.pageDomain = context.rootDomain;
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
PageStore.prototype.createContextFromFrameHostname = function(frameHostname) {
|
||||
var context = µb.tabContextManager.createContext(this.tabId);
|
||||
context.pageHostname = frameHostname;
|
||||
context.pageDomain = µb.URI.domainFromHostname(frameHostname) || frameHostname;
|
||||
return context;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.getNetFilteringSwitch = function() {
|
||||
return µb.tabContextManager.mustLookup(this.tabId).getNetFilteringSwitch();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.getSpecificCosmeticFilteringSwitch = function() {
|
||||
return this.noCosmeticFiltering !== true;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.getGenericCosmeticFilteringSwitch = function() {
|
||||
return this.noGenericCosmeticFiltering !== true &&
|
||||
this.noCosmeticFiltering !== true;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.toggleNetFilteringSwitch = function(url, scope, state) {
|
||||
µb.toggleNetFilteringSwitch(url, scope, state);
|
||||
this.netFilteringCache.empty();
|
||||
@ -562,15 +528,14 @@ PageStore.prototype.journalProcess = function(fromTimer) {
|
||||
}
|
||||
this.journalTimer = null;
|
||||
|
||||
var journal = this.journal,
|
||||
n = journal.length,
|
||||
aggregateCounts = 0,
|
||||
now = Date.now(),
|
||||
pivot = this.journalLastCommitted || 0;
|
||||
const journal = this.journal;
|
||||
const now = Date.now();
|
||||
let aggregateCounts = 0;
|
||||
let pivot = this.journalLastCommitted || 0;
|
||||
|
||||
// Everything after pivot originates from current page.
|
||||
for ( let i = pivot; i < n; i += 2 ) {
|
||||
let hostname = journal[i];
|
||||
for ( let i = pivot; i < journal.length; i += 2 ) {
|
||||
const hostname = journal[i];
|
||||
let hostnameCounts = this.hostnameToCountMap.get(hostname);
|
||||
if ( hostnameCounts === undefined ) {
|
||||
hostnameCounts = 0;
|
||||
@ -605,88 +570,101 @@ PageStore.prototype.journalProcess = function(fromTimer) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.filterRequest = function(context) {
|
||||
this.logData = undefined;
|
||||
PageStore.prototype.filterRequest = function(fctxt) {
|
||||
fctxt.filter = undefined;
|
||||
|
||||
if ( this.getNetFilteringSwitch() === false ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var requestType = context.requestType;
|
||||
const requestType = fctxt.type;
|
||||
|
||||
if ( requestType === 'csp_report' && this.filterCSPReport(context) === 1 ) {
|
||||
if ( requestType === 'csp_report' && this.filterCSPReport(fctxt) === 1 ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( requestType.endsWith('font') && this.filterFont(context) === 1 ) {
|
||||
if ( requestType.endsWith('font') && this.filterFont(fctxt) === 1 ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (
|
||||
requestType === 'script' &&
|
||||
this.filterScripting(context.rootHostname, true) === 1
|
||||
this.filterScripting(fctxt, true) === 1
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
var cacheableResult = this.cacheableResults[requestType] === true;
|
||||
const cacheableResult = this.cacheableResults.has(requestType);
|
||||
|
||||
if ( cacheableResult ) {
|
||||
var entry = this.netFilteringCache.lookupResult(context);
|
||||
const entry = this.netFilteringCache.lookupResult(fctxt);
|
||||
if ( entry !== undefined ) {
|
||||
this.logData = entry.logData;
|
||||
fctxt.filter = entry.logData;
|
||||
return entry.result;
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic URL filtering.
|
||||
var result = µb.sessionURLFiltering.evaluateZ(context.rootHostname, context.requestURL, requestType);
|
||||
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||
this.logData = µb.sessionURLFiltering.toLogData();
|
||||
let result = µb.sessionURLFiltering.evaluateZ(
|
||||
fctxt.getTabHostname(),
|
||||
fctxt.url,
|
||||
requestType
|
||||
);
|
||||
if ( result !== 0 && µb.logger.enabled ) {
|
||||
fctxt.filter = µb.sessionURLFiltering.toLogData();
|
||||
}
|
||||
|
||||
// Dynamic hostname/type filtering.
|
||||
if ( result === 0 && µb.userSettings.advancedUserEnabled ) {
|
||||
result = µb.sessionFirewall.evaluateCellZY(context.rootHostname, context.requestHostname, requestType);
|
||||
if ( result !== 0 && result !== 3 && µb.logger.isEnabled() ) {
|
||||
this.logData = µb.sessionFirewall.toLogData();
|
||||
result = µb.sessionFirewall.evaluateCellZY(
|
||||
fctxt.getTabHostname(),
|
||||
fctxt.getHostname(),
|
||||
requestType
|
||||
);
|
||||
if ( result !== 0 && result !== 3 && µb.logger.enabled ) {
|
||||
fctxt.filter = µb.sessionFirewall.toLogData();
|
||||
}
|
||||
}
|
||||
|
||||
// Static filtering has lowest precedence.
|
||||
if ( result === 0 || result === 3 ) {
|
||||
result = µb.staticNetFilteringEngine.matchString(context);
|
||||
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||
this.logData = µb.staticNetFilteringEngine.toLogData();
|
||||
result = µb.staticNetFilteringEngine.matchString(fctxt);
|
||||
if ( result !== 0 && µb.logger.enabled ) {
|
||||
fctxt.filter = µb.staticNetFilteringEngine.toLogData();
|
||||
}
|
||||
}
|
||||
|
||||
if ( cacheableResult ) {
|
||||
this.netFilteringCache.rememberResult(context, result, this.logData);
|
||||
} else if ( result === 1 && this.collapsibleResources[requestType] === true ) {
|
||||
this.netFilteringCache.rememberBlock(context, true);
|
||||
this.netFilteringCache.rememberResult(fctxt, result, this.logData);
|
||||
} else if ( result === 1 && this.collapsibleResources.has(requestType) ) {
|
||||
this.netFilteringCache.rememberBlock(fctxt, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
PageStore.prototype.cacheableResults = {
|
||||
sub_frame: true
|
||||
};
|
||||
PageStore.prototype.cacheableResults = new Set([
|
||||
'sub_frame',
|
||||
]);
|
||||
|
||||
PageStore.prototype.collapsibleResources = {
|
||||
image: true,
|
||||
media: true,
|
||||
object: true,
|
||||
sub_frame: true
|
||||
};
|
||||
PageStore.prototype.collapsibleResources = new Set([
|
||||
'image',
|
||||
'media',
|
||||
'object',
|
||||
'sub_frame',
|
||||
]);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.filterCSPReport = function(context) {
|
||||
if ( µb.sessionSwitches.evaluateZ('no-csp-reports', context.requestHostname) ) {
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
this.logData = µb.sessionSwitches.toLogData();
|
||||
PageStore.prototype.filterCSPReport = function(fctxt) {
|
||||
if (
|
||||
µb.sessionSwitches.evaluateZ(
|
||||
'no-csp-reports',
|
||||
fctxt.getHostname()
|
||||
)
|
||||
) {
|
||||
if ( µb.logger.enabled ) {
|
||||
fctxt.filter = µb.sessionSwitches.toLogData();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -695,13 +673,18 @@ PageStore.prototype.filterCSPReport = function(context) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.filterFont = function(context) {
|
||||
if ( context.requestType === 'font' ) {
|
||||
PageStore.prototype.filterFont = function(fctxt) {
|
||||
if ( fctxt.type === 'font' ) {
|
||||
this.remoteFontCount += 1;
|
||||
}
|
||||
if ( µb.sessionSwitches.evaluateZ('no-remote-fonts', context.rootHostname) !== false ) {
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
this.logData = µb.sessionSwitches.toLogData();
|
||||
if (
|
||||
µb.sessionSwitches.evaluateZ(
|
||||
'no-remote-fonts',
|
||||
fctxt.getTabHostname()
|
||||
) !== false
|
||||
) {
|
||||
if ( µb.logger.enabled ) {
|
||||
fctxt.filter = µb.sessionSwitches.toLogData();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -710,18 +693,22 @@ PageStore.prototype.filterFont = function(context) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.filterScripting = function(rootHostname, netFiltering) {
|
||||
PageStore.prototype.filterScripting = function(fctxt, netFiltering) {
|
||||
fctxt.filter = undefined;
|
||||
if ( netFiltering === undefined ) {
|
||||
netFiltering = this.getNetFilteringSwitch();
|
||||
}
|
||||
if (
|
||||
netFiltering === false ||
|
||||
µb.sessionSwitches.evaluateZ('no-scripting', rootHostname) === false
|
||||
µb.sessionSwitches.evaluateZ(
|
||||
'no-scripting',
|
||||
fctxt.getTabHostname()
|
||||
) === false
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
this.logData = µb.sessionSwitches.toLogData();
|
||||
if ( µb.logger.enabled ) {
|
||||
fctxt.filter = µb.sessionSwitches.toLogData();
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
@ -730,13 +717,18 @@ PageStore.prototype.filterScripting = function(rootHostname, netFiltering) {
|
||||
|
||||
// The caller is responsible to check whether filtering is enabled or not.
|
||||
|
||||
PageStore.prototype.filterLargeMediaElement = function(size) {
|
||||
this.logData = undefined;
|
||||
PageStore.prototype.filterLargeMediaElement = function(fctxt, size) {
|
||||
fctxt.filter = undefined;
|
||||
|
||||
if ( Date.now() < this.allowLargeMediaElementsUntil ) {
|
||||
return 0;
|
||||
}
|
||||
if ( µb.sessionSwitches.evaluateZ('no-large-media', this.tabHostname) !== true ) {
|
||||
if (
|
||||
µb.sessionSwitches.evaluateZ(
|
||||
'no-large-media',
|
||||
fctxt.getTabHostname()
|
||||
) !== true
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
if ( (size >>> 10) < µb.userSettings.largeMediaSize ) {
|
||||
@ -751,8 +743,8 @@ PageStore.prototype.filterLargeMediaElement = function(size) {
|
||||
);
|
||||
}
|
||||
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
this.logData = µb.sessionSwitches.toLogData();
|
||||
if ( µb.logger.enabled ) {
|
||||
fctxt.filter = µb.sessionSwitches.toLogData();
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -763,26 +755,27 @@ PageStore.prototype.filterLargeMediaElement = function(size) {
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.getBlockedResources = function(request, response) {
|
||||
var µburi = µb.URI,
|
||||
normalURL = µb.normalizePageURL(this.tabId, request.frameURL),
|
||||
frameHostname = µburi.hostnameFromURI(normalURL),
|
||||
resources = request.resources;
|
||||
const normalURL = µb.normalizePageURL(this.tabId, request.frameURL);
|
||||
const resources = request.resources;
|
||||
const fctxt = µBlock.filteringContext;
|
||||
fctxt.fromTabId(this.tabId)
|
||||
.setDocOriginFromURL(normalURL);
|
||||
// Force some resources to go through the filtering engine in order to
|
||||
// populate the blocked-resources cache. This is required because for
|
||||
// some resources it's not possible to detect whether they were blocked
|
||||
// content script-side (i.e. `iframes` -- unlike `img`).
|
||||
if ( Array.isArray(resources) && resources.length !== 0 ) {
|
||||
var context = this.createContextFromFrameHostname(frameHostname);
|
||||
for ( var resource of resources ) {
|
||||
context.requestType = resource.type;
|
||||
context.requestHostname = µburi.hostnameFromURI(resource.url);
|
||||
context.requestURL = resource.url;
|
||||
this.filterRequest(context);
|
||||
for ( const resource of resources ) {
|
||||
this.filterRequest(
|
||||
fctxt.setType(resource.type)
|
||||
.setURL(resource.url)
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( this.netFilteringCache.hash === response.hash ) { return; }
|
||||
response.hash = this.netFilteringCache.hash;
|
||||
response.blockedResources = this.netFilteringCache.lookupAllBlocked(frameHostname);
|
||||
response.blockedResources =
|
||||
this.netFilteringCache.lookupAllBlocked(fctxt.getDocHostname());
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -95,14 +95,14 @@ const RedirectEntry = function() {
|
||||
// - https://stackoverflow.com/a/8056313
|
||||
// - https://bugzilla.mozilla.org/show_bug.cgi?id=998076
|
||||
|
||||
RedirectEntry.prototype.toURL = function(details) {
|
||||
RedirectEntry.prototype.toURL = function(fctxt) {
|
||||
if (
|
||||
this.warURL !== undefined &&
|
||||
details instanceof Object &&
|
||||
details.requestType !== 'xmlhttprequest' &&
|
||||
fctxt instanceof Object &&
|
||||
fctxt.type !== 'xmlhttprequest' &&
|
||||
(
|
||||
suffersSpuriousRedirectConflicts === false ||
|
||||
details.requestURL.startsWith('https:')
|
||||
fctxt.url.startsWith('https:')
|
||||
)
|
||||
) {
|
||||
return this.warURL + '?secret=' + vAPI.warSecret;
|
||||
@ -187,14 +187,14 @@ RedirectEngine.prototype.toBroaderHostname = function(hostname) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
RedirectEngine.prototype.lookup = function(context) {
|
||||
var type = context.requestType;
|
||||
RedirectEngine.prototype.lookup = function(fctxt) {
|
||||
const type = fctxt.type;
|
||||
if ( this.ruleTypes.has(type) === false ) { return; }
|
||||
var src = context.pageHostname,
|
||||
des = context.requestHostname,
|
||||
desAll = this._desAll,
|
||||
reqURL = context.requestURL;
|
||||
var n = 0;
|
||||
const desAll = this._desAll;
|
||||
const reqURL = fctxt.url;
|
||||
let src = fctxt.getDocHostname();
|
||||
let des = fctxt.getHostname();
|
||||
let n = 0;
|
||||
for (;;) {
|
||||
if ( this.ruleDestinations.has(des) ) {
|
||||
desAll[n] = des; n += 1;
|
||||
@ -203,11 +203,10 @@ RedirectEngine.prototype.lookup = function(context) {
|
||||
if ( des === '' ) { break; }
|
||||
}
|
||||
if ( n === 0 ) { return; }
|
||||
var entries;
|
||||
for (;;) {
|
||||
if ( this.ruleSources.has(src) ) {
|
||||
for ( var i = 0; i < n; i++ ) {
|
||||
entries = this.rules.get(src + ' ' + desAll[i] + ' ' + type);
|
||||
for ( let i = 0; i < n; i++ ) {
|
||||
const entries = this.rules.get(src + ' ' + desAll[i] + ' ' + type);
|
||||
if ( entries && this.lookupToken(entries, reqURL) ) {
|
||||
return this.resourceNameRegister;
|
||||
}
|
||||
@ -234,12 +233,12 @@ RedirectEngine.prototype.lookupToken = function(entries, reqURL) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
RedirectEngine.prototype.toURL = function(context) {
|
||||
let token = this.lookup(context);
|
||||
RedirectEngine.prototype.toURL = function(fctxt) {
|
||||
let token = this.lookup(fctxt);
|
||||
if ( token === undefined ) { return; }
|
||||
let entry = this.resources.get(token);
|
||||
if ( entry !== undefined ) {
|
||||
return entry.toURL(context);
|
||||
return entry.toURL(fctxt);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -24,18 +24,26 @@
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.scriptletFilteringEngine = (function() {
|
||||
let api = {};
|
||||
|
||||
let µb = µBlock,
|
||||
scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB(),
|
||||
const µb = µBlock,
|
||||
duplicates = new Set(),
|
||||
acceptedCount = 0,
|
||||
discardedCount = 0,
|
||||
scriptletCache = new µb.MRUCache(32),
|
||||
exceptionsRegister = new Set(),
|
||||
scriptletsRegister = new Map(),
|
||||
exceptionsRegister = new Set(),
|
||||
reEscapeScriptArg = /[\\'"]/g;
|
||||
|
||||
let acceptedCount = 0,
|
||||
discardedCount = 0,
|
||||
scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB();
|
||||
|
||||
const api = {
|
||||
get acceptedCount() {
|
||||
return acceptedCount;
|
||||
},
|
||||
get discardedCount() {
|
||||
return discardedCount;
|
||||
}
|
||||
};
|
||||
|
||||
// Purpose of `contentscriptCode` below is too programmatically inject
|
||||
// content script code which only purpose is to inject scriptlets. This
|
||||
// essentially does the same as what uBO's declarative content script does,
|
||||
@ -58,8 +66,8 @@
|
||||
// Consequently, the programmatic-injection code path is taken only with
|
||||
// Chromium-based browsers.
|
||||
|
||||
let contentscriptCode = (function() {
|
||||
let parts = [
|
||||
const contentscriptCode = (function() {
|
||||
const parts = [
|
||||
'(',
|
||||
function(hostname, scriptlets) {
|
||||
if (
|
||||
@ -163,15 +171,15 @@
|
||||
};
|
||||
})();
|
||||
|
||||
let lookupScriptlet = function(raw, reng, toInject) {
|
||||
const lookupScriptlet = function(raw, reng, toInject) {
|
||||
if ( toInject.has(raw) ) { return; }
|
||||
if ( scriptletCache.resetTime < reng.modifyTime ) {
|
||||
scriptletCache.reset();
|
||||
}
|
||||
var content = scriptletCache.lookup(raw);
|
||||
let content = scriptletCache.lookup(raw);
|
||||
if ( content === undefined ) {
|
||||
var token, args,
|
||||
pos = raw.indexOf(',');
|
||||
const pos = raw.indexOf(',');
|
||||
let token, args;
|
||||
if ( pos === -1 ) {
|
||||
token = raw;
|
||||
} else {
|
||||
@ -196,13 +204,12 @@
|
||||
// Fill template placeholders. Return falsy if:
|
||||
// - At least one argument contains anything else than /\w/ and `.`
|
||||
|
||||
let patchScriptlet = function(content, args) {
|
||||
var i = 1,
|
||||
pos, arg;
|
||||
const patchScriptlet = function(content, args) {
|
||||
let i = 1;
|
||||
while ( args !== '' ) {
|
||||
pos = args.indexOf(',');
|
||||
let pos = args.indexOf(',');
|
||||
if ( pos === -1 ) { pos = args.length; }
|
||||
arg = args.slice(0, pos).trim().replace(reEscapeScriptArg, '\\$&');
|
||||
const arg = args.slice(0, pos).trim().replace(reEscapeScriptArg, '\\$&');
|
||||
content = content.replace('{{' + i + '}}', arg);
|
||||
args = args.slice(pos + 1).trim();
|
||||
i++;
|
||||
@ -210,19 +217,19 @@
|
||||
return content;
|
||||
};
|
||||
|
||||
let logOne = function(isException, token, details) {
|
||||
µb.logger.writeOne(
|
||||
details.tabId,
|
||||
'cosmetic',
|
||||
{
|
||||
const logOne = function(isException, token, details) {
|
||||
µBlock.filteringContext
|
||||
.duplicate()
|
||||
.fromTabId(details.tabId)
|
||||
.setRealm('cosmetic')
|
||||
.setType('dom')
|
||||
.setURL(details.url)
|
||||
.setDocOriginFromURL(details.url)
|
||||
.setFilter({
|
||||
source: 'cosmetic',
|
||||
raw: (isException ? '#@#' : '##') + '+js(' + token + ')'
|
||||
},
|
||||
'dom',
|
||||
details.url,
|
||||
null,
|
||||
details.hostname
|
||||
);
|
||||
})
|
||||
.toLogger();
|
||||
};
|
||||
|
||||
api.reset = function() {
|
||||
@ -254,7 +261,7 @@
|
||||
// because there is no way to create an exception to an exception.
|
||||
|
||||
for ( let hn of parsed.hostnames ) {
|
||||
let negated = hn.charCodeAt(0) === 0x7E /* '~' */;
|
||||
const negated = hn.charCodeAt(0) === 0x7E /* '~' */;
|
||||
if ( negated ) {
|
||||
hn = hn.slice(1);
|
||||
}
|
||||
@ -280,13 +287,13 @@
|
||||
|
||||
while ( reader.next() ) {
|
||||
acceptedCount += 1;
|
||||
let fingerprint = reader.fingerprint();
|
||||
const fingerprint = reader.fingerprint();
|
||||
if ( duplicates.has(fingerprint) ) {
|
||||
discardedCount += 1;
|
||||
continue;
|
||||
}
|
||||
duplicates.add(fingerprint);
|
||||
let args = reader.args();
|
||||
const args = reader.args();
|
||||
if ( args.length < 4 ) { continue; }
|
||||
scriptletDB.add(
|
||||
args[1],
|
||||
@ -299,10 +306,10 @@
|
||||
if ( scriptletDB.size === 0 ) { return; }
|
||||
if ( µb.hiddenSettings.ignoreScriptInjectFilters ) { return; }
|
||||
|
||||
let reng = µb.redirectEngine;
|
||||
const reng = µb.redirectEngine;
|
||||
if ( !reng ) { return; }
|
||||
|
||||
let hostname = request.hostname;
|
||||
const hostname = request.hostname;
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/2835
|
||||
// Do not inject scriptlets if the site is under an `allow` rule.
|
||||
@ -313,8 +320,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
let domain = request.domain,
|
||||
entity = request.entity;
|
||||
const domain = request.domain;
|
||||
const entity = request.entity;
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1954
|
||||
// Implicit
|
||||
@ -322,7 +329,7 @@
|
||||
for (;;) {
|
||||
lookupScriptlet(hn + '.js', reng, scriptletsRegister);
|
||||
if ( hn === domain ) { break; }
|
||||
var pos = hn.indexOf('.');
|
||||
const pos = hn.indexOf('.');
|
||||
if ( pos === -1 ) { break; }
|
||||
hn = hn.slice(pos + 1);
|
||||
}
|
||||
@ -332,16 +339,16 @@
|
||||
|
||||
// Explicit
|
||||
let entries = [];
|
||||
let domainHash = µb.staticExtFilteringEngine.makeHash(domain);
|
||||
const domainHash = µb.staticExtFilteringEngine.makeHash(domain);
|
||||
if ( domainHash !== 0 ) {
|
||||
scriptletDB.retrieve(domainHash, hostname, entries);
|
||||
}
|
||||
let entityHash = µb.staticExtFilteringEngine.makeHash(entity);
|
||||
const entityHash = µb.staticExtFilteringEngine.makeHash(entity);
|
||||
if ( entityHash !== 0 ) {
|
||||
scriptletDB.retrieve(entityHash, entity, entries);
|
||||
}
|
||||
scriptletDB.retrieve(0, hostname, entries);
|
||||
for ( let entry of entries ) {
|
||||
for ( const entry of entries ) {
|
||||
lookupScriptlet(entry.token, reng, scriptletsRegister);
|
||||
}
|
||||
|
||||
@ -356,19 +363,19 @@
|
||||
scriptletDB.retrieve(entityHash | 0b0001, entity, entries);
|
||||
}
|
||||
scriptletDB.retrieve(0 | 0b0001, hostname, entries);
|
||||
for ( let entry of entries ) {
|
||||
for ( const entry of entries ) {
|
||||
exceptionsRegister.add(entry.token);
|
||||
}
|
||||
|
||||
// Return an array of scriptlets, and log results if needed.
|
||||
let out = [],
|
||||
logger = µb.logger.isEnabled() ? µb.logger : null,
|
||||
isException;
|
||||
for ( let entry of scriptletsRegister ) {
|
||||
if ( (isException = exceptionsRegister.has(entry[0])) === false ) {
|
||||
const out = [];
|
||||
const loggerEnabled = µb.logger.enabled;
|
||||
for ( const entry of scriptletsRegister ) {
|
||||
const isException = exceptionsRegister.has(entry[0]);
|
||||
if ( isException === false ) {
|
||||
out.push(entry[1]);
|
||||
}
|
||||
if ( logger !== null ) {
|
||||
if ( loggerEnabled ) {
|
||||
logOne(isException, entry[0], request);
|
||||
}
|
||||
}
|
||||
@ -384,7 +391,7 @@
|
||||
api.injectNow = function(details) {
|
||||
if ( typeof details.frameId !== 'number' ) { return; }
|
||||
if ( µb.URI.isNetworkURI(details.url) === false ) { return; }
|
||||
let request = {
|
||||
const request = {
|
||||
tabId: details.tabId,
|
||||
frameId: details.frameId,
|
||||
url: details.url,
|
||||
@ -394,7 +401,7 @@
|
||||
};
|
||||
request.domain = µb.URI.domainFromHostname(request.hostname);
|
||||
request.entity = µb.URI.entityFromDomain(request.domain);
|
||||
let scriptlets = µb.scriptletFilteringEngine.retrieve(request);
|
||||
const scriptlets = µb.scriptletFilteringEngine.retrieve(request);
|
||||
if ( scriptlets === undefined ) { return; }
|
||||
let code = contentscriptCode.assemble(request.hostname, scriptlets);
|
||||
if ( µb.hiddenSettings.debugScriptlets ) {
|
||||
@ -419,19 +426,6 @@
|
||||
scriptletDB = new µb.staticExtFilteringEngine.HostnameBasedDB(selfie);
|
||||
};
|
||||
|
||||
Object.defineProperties(api, {
|
||||
acceptedCount: {
|
||||
get: function() {
|
||||
return acceptedCount;
|
||||
}
|
||||
},
|
||||
discardedCount: {
|
||||
get: function() {
|
||||
return discardedCount;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return api;
|
||||
})();
|
||||
|
||||
|
@ -663,11 +663,9 @@
|
||||
return compiled;
|
||||
}
|
||||
|
||||
µb.logger.writeOne(
|
||||
'',
|
||||
'error',
|
||||
'Cosmetic filtering – invalid filter: ' + raw
|
||||
);
|
||||
µb.logger.writeOne({
|
||||
error: 'Cosmetic filtering – invalid filter: ' + raw
|
||||
});
|
||||
};
|
||||
|
||||
return entryPoint;
|
||||
|
@ -126,13 +126,6 @@ let pageHostnameRegister = '',
|
||||
|
||||
// Local helpers
|
||||
|
||||
// Be sure to not confuse 'example.com' with 'anotherexample.com'
|
||||
const isFirstParty = function(domain, hostname) {
|
||||
return hostname.endsWith(domain) &&
|
||||
(hostname.length === domain.length ||
|
||||
hostname.charCodeAt(hostname.length - domain.length - 1) === 0x2E /* '.' */);
|
||||
};
|
||||
|
||||
const normalizeRegexSource = function(s) {
|
||||
try {
|
||||
const re = new RegExp(s);
|
||||
@ -2184,12 +2177,10 @@ FilterContainer.prototype.compile = function(raw, writer) {
|
||||
// ORDER OF TESTS IS IMPORTANT!
|
||||
|
||||
// Ignore empty lines
|
||||
var s = raw.trim();
|
||||
if ( s.length === 0 ) {
|
||||
return false;
|
||||
}
|
||||
const s = raw.trim();
|
||||
if ( s.length === 0 ) { return false; }
|
||||
|
||||
var parsed = this.filterParser.parse(s);
|
||||
const parsed = this.filterParser.parse(s);
|
||||
|
||||
// Ignore element-hiding filters
|
||||
if ( parsed.elemHiding ) {
|
||||
@ -2198,7 +2189,9 @@ FilterContainer.prototype.compile = function(raw, writer) {
|
||||
|
||||
// Ignore filters with unsupported options
|
||||
if ( parsed.unsupported ) {
|
||||
µb.logger.writeOne('', 'error', 'Network filtering – invalid filter: ' + raw);
|
||||
µb.logger.writeOne({
|
||||
error: 'Network filtering – invalid filter: ' + raw
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2217,7 +2210,7 @@ FilterContainer.prototype.compile = function(raw, writer) {
|
||||
|
||||
parsed.makeToken();
|
||||
|
||||
var fdata;
|
||||
let fdata;
|
||||
if ( parsed.isRegex ) {
|
||||
fdata = FilterRegex.compile(parsed);
|
||||
} else if ( parsed.hostnamePure ) {
|
||||
@ -2256,7 +2249,7 @@ FilterContainer.prototype.compile = function(raw, writer) {
|
||||
fdata = FilterPlain.compile(parsed);
|
||||
}
|
||||
|
||||
var fwrapped;
|
||||
let fwrapped;
|
||||
if ( parsed.domainOpt !== '' ) {
|
||||
fwrapped = fdata;
|
||||
fdata = FilterOrigin.compile(parsed);
|
||||
@ -2520,24 +2513,22 @@ FilterContainer.prototype.matchStringGenericHide = function(requestURL) {
|
||||
// Some type of requests are exceptional, they need custom handling,
|
||||
// not the generic handling.
|
||||
|
||||
FilterContainer.prototype.matchStringExactType = function(context, requestURL, requestType) {
|
||||
FilterContainer.prototype.matchStringExactType = function(fctxt, requestType) {
|
||||
// Special cases.
|
||||
if ( requestType === 'generichide' ) {
|
||||
return this.matchStringGenericHide(requestURL);
|
||||
return this.matchStringGenericHide(fctxt.url);
|
||||
}
|
||||
let type = typeNameToTypeValue[requestType];
|
||||
if ( type === undefined ) { return 0; }
|
||||
|
||||
// Prime tokenizer: we get a normalized URL in return.
|
||||
let url = this.urlTokenizer.setURL(requestURL);
|
||||
let url = this.urlTokenizer.setURL(fctxt.url);
|
||||
|
||||
// These registers will be used by various filters
|
||||
pageHostnameRegister = context.pageHostname || '';
|
||||
requestHostnameRegister = µb.URI.hostnameFromURI(url);
|
||||
pageHostnameRegister = fctxt.getDocHostname();
|
||||
requestHostnameRegister = fctxt.getHostname();
|
||||
|
||||
let party = isFirstParty(context.pageDomain, requestHostnameRegister)
|
||||
? FirstParty
|
||||
: ThirdParty;
|
||||
let party = fctxt.is3rdPartyToDoc() ? ThirdParty : FirstParty;
|
||||
let categories = this.categories,
|
||||
catBits, bucket;
|
||||
|
||||
@ -2602,15 +2593,15 @@ FilterContainer.prototype.matchStringExactType = function(context, requestURL, r
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.matchString = function(context) {
|
||||
FilterContainer.prototype.matchString = function(fctxt) {
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/519
|
||||
// Use exact type match for anything beyond `other`
|
||||
// Also, be prepared to support unknown types
|
||||
let type = typeNameToTypeValue[context.requestType];
|
||||
let type = typeNameToTypeValue[fctxt.type];
|
||||
if ( type === undefined ) {
|
||||
type = otherTypeBitValue;
|
||||
} else if ( type === 0 || type > otherTypeBitValue ) {
|
||||
return this.matchStringExactType(context, context.requestURL, context.requestType);
|
||||
return this.matchStringExactType(fctxt, fctxt.type);
|
||||
}
|
||||
|
||||
// The logic here is simple:
|
||||
@ -2635,17 +2626,17 @@ FilterContainer.prototype.matchString = function(context) {
|
||||
// filter.
|
||||
|
||||
// Prime tokenizer: we get a normalized URL in return.
|
||||
let url = this.urlTokenizer.setURL(context.requestURL);
|
||||
let url = this.urlTokenizer.setURL(fctxt.url);
|
||||
|
||||
// These registers will be used by various filters
|
||||
pageHostnameRegister = context.pageHostname || '';
|
||||
requestHostnameRegister = context.requestHostname;
|
||||
pageHostnameRegister = fctxt.getDocHostname();
|
||||
requestHostnameRegister = fctxt.getHostname();
|
||||
|
||||
this.fRegister = null;
|
||||
|
||||
let party = isFirstParty(context.pageDomain, context.requestHostname)
|
||||
? FirstParty
|
||||
: ThirdParty;
|
||||
let party = fctxt.is3rdPartyToDoc()
|
||||
? ThirdParty
|
||||
: FirstParty;
|
||||
let categories = this.categories,
|
||||
catBits, bucket;
|
||||
|
||||
|
179
src/js/tab.js
179
src/js/tab.js
@ -215,6 +215,7 @@ housekeep itself.
|
||||
this.stack = [];
|
||||
this.rawURL =
|
||||
this.normalURL =
|
||||
this.origin =
|
||||
this.rootHostname =
|
||||
this.rootDomain = '';
|
||||
this.commitTimer = null;
|
||||
@ -305,14 +306,21 @@ housekeep itself.
|
||||
TabContext.prototype.update = function() {
|
||||
this.netFilteringReadTime = 0;
|
||||
if ( this.stack.length === 0 ) {
|
||||
this.rawURL = this.normalURL = this.rootHostname = this.rootDomain = '';
|
||||
this.rawURL =
|
||||
this.normalURL =
|
||||
this.origin =
|
||||
this.rootHostname =
|
||||
this.rootDomain = '';
|
||||
return;
|
||||
}
|
||||
var stackEntry = this.stack[this.stack.length - 1];
|
||||
this.rawURL = stackEntry.url;
|
||||
this.normalURL = µb.normalizePageURL(this.tabId, this.rawURL);
|
||||
this.rootHostname = µb.URI.hostnameFromURI(this.normalURL);
|
||||
this.rootDomain = µb.URI.domainFromHostname(this.rootHostname) || this.rootHostname;
|
||||
this.origin = µb.URI.originFromURI(this.normalURL);
|
||||
this.rootHostname = µb.URI.hostnameFromURI(this.origin);
|
||||
this.rootDomain =
|
||||
µb.URI.domainFromHostname(this.rootHostname) ||
|
||||
this.rootHostname;
|
||||
};
|
||||
|
||||
// Called whenever a candidate root URL is spotted for the tab.
|
||||
@ -431,15 +439,13 @@ housekeep itself.
|
||||
|
||||
// Behind-the-scene tab context
|
||||
(function() {
|
||||
var entry = new TabContext(vAPI.noTabId);
|
||||
const entry = new TabContext(vAPI.noTabId);
|
||||
entry.stack.push(new StackEntry('', true));
|
||||
entry.rawURL = '';
|
||||
entry.normalURL = µb.normalizePageURL(entry.tabId);
|
||||
entry.rootHostname = µb.URI.hostnameFromURI(entry.normalURL);
|
||||
entry.origin = µb.URI.originFromURI(entry.normalURL);
|
||||
entry.rootHostname = µb.URI.hostnameFromURI(entry.origin);
|
||||
entry.rootDomain = µb.URI.domainFromHostname(entry.rootHostname);
|
||||
|
||||
entry = new TabContext(vAPI.anyTabId);
|
||||
entry.stack.push(new StackEntry('', true));
|
||||
})();
|
||||
|
||||
// Context object, typically to be used to feed filtering engines.
|
||||
@ -454,6 +460,7 @@ housekeep itself.
|
||||
this.pageHostname =
|
||||
this.pageDomain =
|
||||
this.requestURL =
|
||||
this.origin =
|
||||
this.requestHostname =
|
||||
this.requestDomain = '';
|
||||
return this;
|
||||
@ -550,8 +557,7 @@ vAPI.tabs.onClosed = function(tabId) {
|
||||
vAPI.tabs.onPopupUpdated = (function() {
|
||||
// The same context object will be reused everytime. This also allows to
|
||||
// remember whether a popup or popunder was matched.
|
||||
var context = {},
|
||||
logData;
|
||||
const fctxt = µBlock.filteringContext.setFilter(undefined);
|
||||
|
||||
// https://github.com/gorhill/uBlock/commit/1d448b85b2931412508aa01bf899e0b6f0033626#commitcomment-14944764
|
||||
// See if two URLs are different, disregarding scheme -- because the
|
||||
@ -560,10 +566,10 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
// Maybe no link element was clicked.
|
||||
// https://github.com/gorhill/uBlock/issues/3287
|
||||
// Do not bail out if the target URL has no hostname.
|
||||
var areDifferentURLs = function(a, b) {
|
||||
const areDifferentURLs = function(a, b) {
|
||||
if ( b === '' ) { return true; }
|
||||
if ( b.startsWith('about:') ) { return false; }
|
||||
var pos = a.indexOf('://');
|
||||
let pos = a.indexOf('://');
|
||||
if ( pos === -1 ) { return false; }
|
||||
a = a.slice(pos);
|
||||
pos = b.indexOf('://');
|
||||
@ -573,19 +579,12 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
return b !== a;
|
||||
};
|
||||
|
||||
var popupMatch = function(openerURL, targetURL, popupType) {
|
||||
var openerHostname = µb.URI.hostnameFromURI(openerURL),
|
||||
openerDomain = µb.URI.domainFromHostname(openerHostname),
|
||||
result;
|
||||
|
||||
context.pageHostname = openerHostname;
|
||||
context.pageDomain = openerDomain;
|
||||
context.rootURL = openerURL;
|
||||
context.rootHostname = openerHostname;
|
||||
context.rootDomain = openerDomain;
|
||||
context.requestURL = targetURL;
|
||||
context.requestHostname = µb.URI.hostnameFromURI(targetURL);
|
||||
context.requestType = 'popup';
|
||||
const popupMatch = function(openerURL, targetURL, popupType) {
|
||||
fctxt.setTabOriginFromURL(openerURL)
|
||||
.setDocOriginFromURL(openerURL)
|
||||
.setURL(targetURL)
|
||||
.setType('popup');
|
||||
let result;
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1735
|
||||
// Do not bail out on `data:` URI, they are commonly used for popups.
|
||||
@ -603,16 +602,19 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
// Ignore bad target URL. On Firefox, an `about:blank` tab may be
|
||||
// opened for a new tab before it is filled in with the real target
|
||||
// URL.
|
||||
if ( openerHostname !== '' && targetURL !== 'about:blank' ) {
|
||||
if ( fctxt.getTabHostname() !== '' && targetURL !== 'about:blank' ) {
|
||||
// Check per-site switch first
|
||||
// https://github.com/gorhill/uBlock/issues/3060
|
||||
// - The no-popups switch must apply only to popups, not to
|
||||
// popunders.
|
||||
if (
|
||||
popupType === 'popup' &&
|
||||
µb.sessionSwitches.evaluateZ('no-popups', openerHostname)
|
||||
µb.sessionSwitches.evaluateZ(
|
||||
'no-popups',
|
||||
fctxt.getTabHostname()
|
||||
)
|
||||
) {
|
||||
logData = {
|
||||
fctxt.filter = {
|
||||
raw: 'no-popups: ' + µb.sessionSwitches.z + ' true',
|
||||
result: 1,
|
||||
source: 'switch'
|
||||
@ -624,7 +626,7 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
// Take into account popup-specific rules in dynamic URL
|
||||
// filtering, OR generic allow rules.
|
||||
result = µb.sessionURLFiltering.evaluateZ(
|
||||
openerHostname,
|
||||
fctxt.getTabHostname(),
|
||||
targetURL,
|
||||
popupType
|
||||
);
|
||||
@ -632,7 +634,7 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
result === 1 && µb.sessionURLFiltering.type === popupType ||
|
||||
result === 2
|
||||
) {
|
||||
logData = µb.sessionURLFiltering.toLogData();
|
||||
fctxt.filter = µb.sessionURLFiltering.toLogData();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -641,12 +643,12 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
// rules are ignored, as block rules are not meant to block
|
||||
// specific types like `popup` (just like with static filters).
|
||||
result = µb.sessionFirewall.evaluateCellZY(
|
||||
openerHostname,
|
||||
context.requestHostname,
|
||||
fctxt.getTabHostname(),
|
||||
fctxt.getHostname(),
|
||||
popupType
|
||||
);
|
||||
if ( result === 2 ) {
|
||||
logData = µb.sessionFirewall.toLogData();
|
||||
fctxt.filter = µb.sessionFirewall.toLogData();
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
@ -656,12 +658,11 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
// Don't block if uBlock is turned off in popup's context
|
||||
if ( µb.getNetFilteringSwitch(targetURL) ) {
|
||||
result = µb.staticNetFilteringEngine.matchStringExactType(
|
||||
context,
|
||||
targetURL,
|
||||
fctxt,
|
||||
popupType
|
||||
);
|
||||
if ( result !== 0 ) {
|
||||
logData = µb.staticNetFilteringEngine.toLogData();
|
||||
fctxt.filter = µb.staticNetFilteringEngine.toLogData();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -669,23 +670,23 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
var mapPopunderResult = function(popunderURL, popunderHostname, result) {
|
||||
const mapPopunderResult = function(popunderURL, popunderHostname, result) {
|
||||
if (
|
||||
logData === undefined ||
|
||||
logData.source !== 'static' ||
|
||||
logData.token === µb.staticNetFilteringEngine.noTokenHash
|
||||
fctxt.filter === undefined ||
|
||||
fctxt.filter !== 'static' ||
|
||||
fctxt.filter.token === µb.staticNetFilteringEngine.noTokenHash
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
if ( logData.token === µb.staticNetFilteringEngine.dotTokenHash ) {
|
||||
if ( fctxt.filter.token === µb.staticNetFilteringEngine.dotTokenHash ) {
|
||||
return result;
|
||||
}
|
||||
var re = new RegExp(logData.regex, 'i'),
|
||||
matches = re.exec(popunderURL);
|
||||
const re = new RegExp(fctxt.filter.regex, 'i');
|
||||
const matches = re.exec(popunderURL);
|
||||
if ( matches === null ) { return 0; }
|
||||
var beg = matches.index,
|
||||
end = beg + matches[0].length,
|
||||
pos = popunderURL.indexOf(popunderHostname);
|
||||
const beg = matches.index;
|
||||
const end = beg + matches[0].length;
|
||||
const pos = popunderURL.indexOf(popunderHostname);
|
||||
if ( pos === -1 ) { return 0; }
|
||||
// https://github.com/gorhill/uBlock/issues/1471
|
||||
// We test whether the opener hostname as at least one character
|
||||
@ -698,36 +699,32 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
: 0;
|
||||
};
|
||||
|
||||
var popunderMatch = function(openerURL, targetURL) {
|
||||
var result = popupMatch(targetURL, openerURL, 'popunder');
|
||||
if ( result === 1 ) {
|
||||
return result;
|
||||
}
|
||||
const popunderMatch = function(openerURL, targetURL) {
|
||||
let result = popupMatch(targetURL, openerURL, 'popunder');
|
||||
if ( result === 1 ) { return result; }
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1010#issuecomment-186824878
|
||||
// Check the opener tab as if it were the newly opened tab: if there
|
||||
// is a hit against a popup filter, and if the matching filter is not
|
||||
// a broad one, we will consider the opener tab to be a popunder tab.
|
||||
// For now, a "broad" filter is one which does not touch any part of
|
||||
// the hostname part of the opener URL.
|
||||
var popunderURL = openerURL,
|
||||
let popunderURL = openerURL,
|
||||
popunderHostname = µb.URI.hostnameFromURI(popunderURL);
|
||||
if ( popunderHostname === '' ) {
|
||||
return 0;
|
||||
}
|
||||
if ( popunderHostname === '' ) { return 0; }
|
||||
|
||||
result = mapPopunderResult(
|
||||
popunderURL,
|
||||
popunderHostname,
|
||||
popupMatch(targetURL, popunderURL, 'popup')
|
||||
);
|
||||
if ( result !== 0 ) {
|
||||
return result;
|
||||
}
|
||||
if ( result !== 0 ) { return result; }
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1598
|
||||
// Try to find a match against origin part of the opener URL.
|
||||
// Try to find a match against origin part of the opener URL.
|
||||
popunderURL = µb.URI.originFromURI(popunderURL);
|
||||
if ( popunderURL === '' ) {
|
||||
return 0;
|
||||
}
|
||||
if ( popunderURL === '' ) { return 0; }
|
||||
|
||||
return mapPopunderResult(
|
||||
popunderURL,
|
||||
popunderHostname,
|
||||
@ -737,40 +734,43 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
|
||||
return function(targetTabId, openerDetails) {
|
||||
// Opener details.
|
||||
var openerTabId = openerDetails.tabId;
|
||||
var tabContext = µb.tabContextManager.lookup(openerTabId);
|
||||
const openerTabId = openerDetails.tabId;
|
||||
let tabContext = µb.tabContextManager.lookup(openerTabId);
|
||||
if ( tabContext === null ) { return; }
|
||||
var openerURL = tabContext.rawURL;
|
||||
const openerURL = tabContext.rawURL;
|
||||
if ( openerURL === '' ) { return; }
|
||||
|
||||
// Popup details.
|
||||
tabContext = µb.tabContextManager.lookup(targetTabId);
|
||||
if ( tabContext === null ) { return; }
|
||||
var targetURL = tabContext.rawURL;
|
||||
let targetURL = tabContext.rawURL;
|
||||
if ( targetURL === '' ) { return; }
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/341
|
||||
// Allow popups if uBlock is turned off in opener's context.
|
||||
if ( µb.getNetFilteringSwitch(openerURL) === false ) {
|
||||
return;
|
||||
}
|
||||
if ( µb.getNetFilteringSwitch(openerURL) === false ) { return; }
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1538
|
||||
if ( µb.getNetFilteringSwitch(µb.normalizePageURL(openerTabId, openerURL)) === false ) {
|
||||
if (
|
||||
µb.getNetFilteringSwitch(µb.normalizePageURL(
|
||||
openerTabId,
|
||||
openerURL)
|
||||
) === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the page URL is that of our "blocked page" URL, extract the URL of
|
||||
// the page which was blocked.
|
||||
if ( targetURL.startsWith(vAPI.getURL('document-blocked.html')) ) {
|
||||
var matches = /details=([^&]+)/.exec(targetURL);
|
||||
const matches = /details=([^&]+)/.exec(targetURL);
|
||||
if ( matches !== null ) {
|
||||
targetURL = JSON.parse(atob(matches[1])).url;
|
||||
}
|
||||
}
|
||||
|
||||
// Popup test.
|
||||
var popupType = 'popup',
|
||||
let popupType = 'popup',
|
||||
result = 0;
|
||||
// https://github.com/gorhill/uBlock/issues/2919
|
||||
// - If the target tab matches a clicked link, assume it's legit.
|
||||
@ -788,18 +788,21 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
|
||||
// Log only for when there was a hit against an actual filter (allow or block).
|
||||
// https://github.com/gorhill/uBlock/issues/2776
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
µb.logger.writeOne(
|
||||
popupType === 'popup' ? openerTabId : targetTabId,
|
||||
'net',
|
||||
result !== 0 ? logData : undefined,
|
||||
popupType,
|
||||
popupType === 'popup' ? targetURL : openerURL,
|
||||
µb.URI.hostnameFromURI(context.rootURL),
|
||||
µb.URI.hostnameFromURI(context.rootURL)
|
||||
);
|
||||
if ( µb.logger.enabled ) {
|
||||
fctxt.setRealm('net').setType(popupType);
|
||||
if ( popupType === 'popup' ) {
|
||||
fctxt.setURL(targetURL)
|
||||
.setTabId(openerTabId)
|
||||
.setTabOriginFromURL(openerURL)
|
||||
.setDocOriginFromURL(openerURL);
|
||||
} else {
|
||||
fctxt.setURL(openerURL)
|
||||
.setTabId(targetTabId)
|
||||
.setTabOriginFromURL(targetURL)
|
||||
.setDocOriginFromURL(targetURL);
|
||||
}
|
||||
fctxt.toLogger();
|
||||
}
|
||||
logData = undefined;
|
||||
|
||||
// Not blocked
|
||||
if ( result !== 1 ) {
|
||||
@ -808,9 +811,9 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||
|
||||
// Only if a popup was blocked do we report it in the dynamic
|
||||
// filtering pane.
|
||||
var pageStore = µb.pageStoreFromTabId(openerTabId);
|
||||
const pageStore = µb.pageStoreFromTabId(openerTabId);
|
||||
if ( pageStore ) {
|
||||
pageStore.journalAddRequest(context.requestHostname, result);
|
||||
pageStore.journalAddRequest(fctxt.getHostname(), result);
|
||||
pageStore.popupBlockedCount += 1;
|
||||
}
|
||||
|
||||
@ -910,13 +913,9 @@ vAPI.tabs.registerListeners();
|
||||
// Permanent page store for behind-the-scene requests. Must never be removed.
|
||||
|
||||
(function() {
|
||||
var pageStore = µb.PageStore.factory(vAPI.noTabId);
|
||||
const pageStore = µb.PageStore.factory(vAPI.noTabId);
|
||||
µb.pageStores.set(pageStore.tabId, pageStore);
|
||||
pageStore.title = vAPI.i18n('logBehindTheScene');
|
||||
|
||||
pageStore = µb.PageStore.factory(vAPI.anyTabId);
|
||||
µb.pageStores.set(pageStore.tabId, pageStore);
|
||||
pageStore.title = '[Any one of the known tabs]';
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -538,7 +538,7 @@ var matchBucket = function(url, hostname, bucket, start) {
|
||||
// cosmetic filters.
|
||||
|
||||
µBlock.logCosmeticFilters = function(tabId, frameId) {
|
||||
if ( this.logger.isEnabled() ) {
|
||||
if ( this.logger.enabled ) {
|
||||
vAPI.tabs.injectScript(tabId, {
|
||||
file: '/js/scriptlets/cosmetic-logger.js',
|
||||
frameId: frameId,
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2014-2018 Raymond Hill
|
||||
Copyright (C) 2014-present 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
|
||||
@ -51,7 +51,7 @@ var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/;
|
||||
// Derived
|
||||
var reSchemeFromURI = /^[^:\/?#]+:/;
|
||||
var reAuthorityFromURI = /^(?:[^:\/?#]+:)?(\/\/[^\/?#]+)/;
|
||||
var reOriginFromURI = /^(?:[^:\/?#]+:)\/\/(?:[^\/?#]+)?/;
|
||||
var reOriginFromURI = /^(?:[^:\/?#]+:)\/\/[^\/?#]+/;
|
||||
var reCommonHostnameFromURL = /^https?:\/\/([0-9a-z_][0-9a-z._-]*[0-9a-z])\//;
|
||||
var rePathFromURI = /^(?:[^:\/?#]+:)?(?:\/\/[^\/?#]*)?([^?#]*)/;
|
||||
var reMustNormalizeHostname = /[^0-9a-z._-]/;
|
||||
@ -225,7 +225,7 @@ URI.assemble = function(bits) {
|
||||
/******************************************************************************/
|
||||
|
||||
URI.originFromURI = function(uri) {
|
||||
var matches = reOriginFromURI.exec(uri);
|
||||
const matches = reOriginFromURI.exec(uri);
|
||||
return matches !== null ? matches[0].toLowerCase() : '';
|
||||
};
|
||||
|
||||
|
@ -37,14 +37,14 @@
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var exceptions = new Map();
|
||||
var rules = new Map();
|
||||
let exceptions = new Map();
|
||||
let rules = new Map();
|
||||
|
||||
// This value dictate how the search will be performed:
|
||||
// < this.cutoffLength = indexOf()
|
||||
// >= this.cutoffLength = binary search
|
||||
var cutoffLength = 256;
|
||||
var mustPunycode = /[^a-z0-9.-]/;
|
||||
const cutoffLength = 256;
|
||||
const mustPunycode = /[^a-z0-9.-]/;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@ -284,7 +284,7 @@ function crystallize(store) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var selfieMagic = 1;
|
||||
const selfieMagic = 1;
|
||||
|
||||
function toSelfie() {
|
||||
return {
|
||||
@ -311,12 +311,15 @@ function fromSelfie(selfie) {
|
||||
root = root || window;
|
||||
|
||||
root.publicSuffixList = {
|
||||
'version': '1.0',
|
||||
'parse': parse,
|
||||
'getDomain': getDomain,
|
||||
'getPublicSuffix': getPublicSuffix,
|
||||
'toSelfie': toSelfie,
|
||||
'fromSelfie': fromSelfie,
|
||||
version: '1.0',
|
||||
parse: parse,
|
||||
getDomain: getDomain,
|
||||
getPublicSuffix: getPublicSuffix,
|
||||
toSelfie: toSelfie,
|
||||
fromSelfie: fromSelfie,
|
||||
get empty() {
|
||||
return rules.size === 0;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -17,8 +17,9 @@
|
||||
<option value="tab_bts" data-i18n="logBehindTheScene">
|
||||
<option value="tab_active" data-i18n="loggerCurrentTab">
|
||||
</select>
|
||||
<span id="refresh" class="button fa disabled needtab"></span>
|
||||
<span id="showdom" class="button fa"></span>
|
||||
<span id="refresh" class="button fa disabled needdom"></span>
|
||||
<span id="showdom" class="button fa disabled needdom"></span>
|
||||
<span id="showpopup" class="button disabled needscope"><img src="/img/icon_64.png"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -37,7 +38,6 @@
|
||||
<ul id="domTree"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="netInspector" class="inspector vCompact f">
|
||||
<div class="permatoolbar">
|
||||
<div>
|
||||
@ -50,21 +50,17 @@
|
||||
</div>
|
||||
<div class="vscrollable">
|
||||
<style id="tabFilterer"></style>
|
||||
<style id="popupFilterer"></style>
|
||||
<table>
|
||||
<colgroup><col><col><col><col><col></colgroup>
|
||||
<colgroup><col><col><col><col><col><col></colgroup>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
<div id="popupContainer">
|
||||
<div><span></span> <span></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<iframe id="popupContainer" class="hide"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="templates" style="display: none;">
|
||||
<div id="renderedURLTemplate"><span><span></span><b></b><span></span></span></div>
|
||||
<div id="hiddenTemplate"><span style="display:none;"></span></div>
|
||||
<div id="netFilteringDialog" class="modalDialog">
|
||||
<div class="dialog">
|
||||
<div class="hide preview"></div>
|
||||
|
Loading…
Reference in New Issue
Block a user