mirror of
https://github.com/gorhill/uMatrix.git
synced 2024-05-19 03:33:17 +12:00
fix https://github.com/gorhill/uMatrix/issues/951, https://github.com/uBlockOrigin/uMatrix-issues/issues/62
This commit is contained in:
parent
cb2ab59297
commit
2256552899
|
@ -31,6 +31,9 @@
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
body[dir="ltr"] {
|
||||
direction: ltr;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ input:focus {
|
|||
width: 4.6em;
|
||||
}
|
||||
#content table > colgroup > col:nth-of-type(2) {
|
||||
width: 2.2em;
|
||||
width: 30%;
|
||||
}
|
||||
#content table > colgroup > col:nth-of-type(3) {
|
||||
width: 2.2em;
|
||||
|
@ -101,7 +101,7 @@ input:focus {
|
|||
width: 5.4em;
|
||||
}
|
||||
#content table > colgroup > col:nth-of-type(5) {
|
||||
width: calc(100% - 14.4em);
|
||||
width: calc(100% - 4.6em - 30% - 2.2em - 5.4em);
|
||||
}
|
||||
#content table tr {
|
||||
background-color: #fafafa;
|
||||
|
@ -151,13 +151,8 @@ body.compactView #content tr:not(.vExpanded) td {
|
|||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#content table tr td:nth-of-type(2) {
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#content table tr.tab_bts > td:nth-of-type(2):before {
|
||||
content: '\f070';
|
||||
font: 1em FontAwesome;
|
||||
#content table tr td:nth-of-type(2):not([colspan]) {
|
||||
text-align: right;
|
||||
}
|
||||
#content table tr.tab:not(.canMtx) {
|
||||
opacity: 0.3;
|
||||
|
@ -165,17 +160,8 @@ body.compactView #content tr:not(.vExpanded) td {
|
|||
#content table tr.tab:not(.canMtx):hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
#content table tr.tab:not(.canMtx) > td:nth-of-type(2):before {
|
||||
content: '\f00d';
|
||||
font: 1em FontAwesome;
|
||||
}
|
||||
body:not(.popupOn) #content table tr.canMtx td:nth-of-type(2) {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
body:not(.popupOn) #content table tr.canMtx td:nth-of-type(2):hover {
|
||||
background: #ccc;
|
||||
}
|
||||
#content table tr.cat_net td:nth-of-type(3) {
|
||||
cursor: pointer;
|
||||
font: 12px monospace;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
@ -189,45 +175,232 @@ body:not(.popupOn) #content table tr.canMtx td:nth-of-type(2):hover {
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
#popupContainer {
|
||||
background: white;
|
||||
border: 1px solid gray;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
.modalDialog {
|
||||
align-items: center;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
justify-content: center;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 1em;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
width: 100vw;
|
||||
z-index: 1000;
|
||||
}
|
||||
body.popupOn #popupContainer {
|
||||
display: block;
|
||||
.modalDialog > .dialog {
|
||||
background-color: white;
|
||||
font: 15px httpsb,sans-serif;
|
||||
min-width: fit-content;
|
||||
padding: 0.5em;
|
||||
width: 90%;
|
||||
}
|
||||
#popupContainer > div {
|
||||
background: #888;
|
||||
|
||||
#ruleEditor section {
|
||||
display: flex;
|
||||
}
|
||||
.scopeWidget {
|
||||
line-height: 2.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
#specificScope, .ruleCell:nth-of-type(1) {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#globalScope, .ruleCell:nth-of-type(2) {
|
||||
width: 4em;
|
||||
}
|
||||
.ruleEditorToolbar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.ruleEditorToolbar button {
|
||||
background-color: white;
|
||||
border: 0;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0.2em;
|
||||
position: relative;
|
||||
}
|
||||
#popupContainer > div {
|
||||
text-align: right;
|
||||
.ruleEditorToolbar button:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
#popupContainer > div > span {
|
||||
.ruleEditorToolbar button.disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
.ruleEditorToolbar button.fa {
|
||||
font: 1.7em FontAwesome;
|
||||
min-width: 1.5em;
|
||||
}
|
||||
.ruleEditorToolbar button > span.badge {
|
||||
background-color: rgba(240,240,240,0.75);
|
||||
bottom: 1px;
|
||||
color: #000;
|
||||
display: inline-block;
|
||||
font-family: sans-serif;
|
||||
font-size: 40%;
|
||||
padding: 1px 1px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
}
|
||||
.ruleEditorToolbar button.disabled > span.badge {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button.scopeRel {
|
||||
color: #24c;
|
||||
}
|
||||
body[data-scope="*"] button.scopeRel {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.ruleWidgets {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.ruleRow {
|
||||
display: flex;
|
||||
line-height: 2em;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.ruleCell {
|
||||
background-color: #eee;
|
||||
border: 1px dotted rgba(0,0,0,0.2);
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font: 14px FontAwesome;
|
||||
padding: 3px;
|
||||
margin-left: 1px;
|
||||
padding: 1px;
|
||||
position: relative;
|
||||
}
|
||||
#popupContainer > div > span:hover {
|
||||
.ruleCell:hover {
|
||||
border-style: solid;
|
||||
}
|
||||
.ruleCell:nth-of-type(1) {
|
||||
margin-left: 0;
|
||||
text-align: right;
|
||||
}
|
||||
.ruleCell:nth-of-type(2) {
|
||||
text-align: center;
|
||||
}
|
||||
.ruleCell[data-tcolor="1"] {
|
||||
border-color: #debaba;
|
||||
color: black;
|
||||
background-color: #f8d0d0;
|
||||
}
|
||||
#ruleEditor.colorblind .ruleCell[data-tcolor="1"] {
|
||||
border-color: rgba(0, 19, 110, 0.3);
|
||||
color: black;
|
||||
background-color: rgba(0, 19, 110, 0.2);
|
||||
}
|
||||
.ruleCell[data-tcolor="2"] {
|
||||
border-color: #bad6ba;
|
||||
color: black;
|
||||
background-color: #d0f0d0;
|
||||
}
|
||||
#ruleEditor.colorblind .ruleCell[data-tcolor="2"] {
|
||||
border-color: rgba(255, 194, 57, 0.3);
|
||||
color: black;
|
||||
background-color: rgba(255, 194, 57, 0.2);
|
||||
}
|
||||
.ruleCell[data-tcolor="129"] {
|
||||
color: white;
|
||||
background-color: #c00;
|
||||
}
|
||||
#popupContainer > iframe {
|
||||
#ruleEditor.colorblind .ruleCell[data-tcolor="129"] {
|
||||
color: white;
|
||||
background-color: rgb(0, 19, 110);
|
||||
}
|
||||
.ruleCell[data-tcolor="130"] {
|
||||
color: white;
|
||||
background-color: #080;
|
||||
}
|
||||
#ruleEditor.colorblind .ruleCell[data-tcolor="130"] {
|
||||
border-color: rgb(255, 194, 57);
|
||||
color: black;
|
||||
background-color: rgb(255, 194, 57);
|
||||
}
|
||||
.ruleCell[data-pcolor="129"] {
|
||||
background-image: url('../img/permanent-black-small.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: -1px -1px;
|
||||
}
|
||||
#ruleEditor.colorblind .ruleCell[data-pcolor="129"] {
|
||||
background-image: url('../img/permanent-black-small-cb.png');
|
||||
}
|
||||
.ruleCell[data-pcolor="130"] {
|
||||
background-image: url('../img/permanent-white-small.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: -1px -1px;
|
||||
}
|
||||
#ruleEditor.colorblind .ruleCell[data-pcolor="130"] {
|
||||
background-image: url('../img/permanent-white-small-cb.png');
|
||||
}
|
||||
|
||||
#ruleActionPicker {
|
||||
border: 0;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
}
|
||||
.allowRule, .blockRule {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
background: transparent;
|
||||
}
|
||||
#popupContainer.hide {
|
||||
width: 6em !important;
|
||||
.allowRule {
|
||||
top: 0;
|
||||
}
|
||||
#popupContainer.hide > iframe {
|
||||
display: none;
|
||||
.blockRule {
|
||||
top: 50%;
|
||||
}
|
||||
.ruleCell[data-tcolor="1"] .allowRule:hover {
|
||||
background-color: #080;
|
||||
opacity: 0.25;
|
||||
}
|
||||
.ruleCell[data-tcolor="1"] .blockRule:hover {
|
||||
background-color: #c00;
|
||||
opacity: 0.25;
|
||||
}
|
||||
.ruleCell[data-tcolor="2"] .allowRule:hover {
|
||||
background-color: #080;
|
||||
opacity: 0.25;
|
||||
}
|
||||
.ruleCell[data-tcolor="2"] .blockRule:hover {
|
||||
background-color: #c00;
|
||||
opacity: 0.25;
|
||||
}
|
||||
.ruleCell[data-tcolor="129"] .allowRule:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
.ruleCell[data-tcolor="129"] .blockRule:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
.ruleCell[data-pcolor="130"] .allowRule:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
.ruleCell[data-pcolor="130"] .blockRule:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
#ruleEditor.colorblind .ruleCell[data-tcolor="1"] .allowRule:hover,
|
||||
#ruleEditor.colorblind .ruleCell[data-tcolor="2"] .allowRule:hover {
|
||||
background-color: rgb(255, 194, 57);
|
||||
opacity: 0.6;
|
||||
}
|
||||
#ruleEditor.colorblind .ruleCell[data-tcolor="1"] .blockRule:hover,
|
||||
#ruleEditor.colorblind .ruleCell[data-tcolor="2"] .blockRule:hover {
|
||||
background-color: rgb(0, 19, 110);
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,24 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a browser extension to black/white list requests.
|
||||
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
|
||||
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/uMatrix
|
||||
*/
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
border: 0;
|
||||
|
@ -301,76 +322,13 @@ button.disabled > span.badge {
|
|||
display: block;
|
||||
}
|
||||
|
||||
body .toolbar .scope {
|
||||
background-color: #ccc;
|
||||
border: 1px solid #ccc;
|
||||
box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
display: inline-flex;
|
||||
color: white;
|
||||
margin: 0;
|
||||
padding: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
body .toolbar .scope > span {
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
body .toolbar .scope > span > span {
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
body .toolbar #specificScope {
|
||||
direction: ltr;
|
||||
justify-content: flex-end;
|
||||
width: 16em;
|
||||
}
|
||||
body .toolbar #specificScope.on {
|
||||
background-color: #24c;
|
||||
border-color: #24c;
|
||||
}
|
||||
body .toolbar #specificScope > span {
|
||||
background-color: #ccc;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
body .toolbar #specificScope > span.on {
|
||||
background-color: #24c;
|
||||
}
|
||||
body .toolbar #specificScope > span:first-of-type:not(.on):hover,
|
||||
body .toolbar #specificScope > span:first-of-type:not(.on):hover ~ span:not(.on),
|
||||
body .toolbar #specificScope > span:not(.on) + span:not(.on):hover,
|
||||
body .toolbar #specificScope > span:not(.on) + span:not(.on):hover ~ span:not(.on) {
|
||||
background-color: #999;
|
||||
}
|
||||
body .toolbar #specificScope > span:first-of-type:not(.on):hover ~ span,
|
||||
body .toolbar #specificScope > span:not(.on) + span:not(.on):hover ~ span,
|
||||
body .toolbar #specificScope > span.on + span:hover,
|
||||
body .toolbar #specificScope > span.on + span:hover ~ span {
|
||||
background-color: #139;
|
||||
}
|
||||
body .toolbar #specificScope > span:first-of-type {
|
||||
flex: 1;
|
||||
}
|
||||
body .toolbar #globalScope {
|
||||
justify-content: center;
|
||||
margin-left: 1px;
|
||||
width: 1.6em;
|
||||
}
|
||||
body .toolbar #globalScope.on {
|
||||
background-color: #000;
|
||||
border-color: #000;
|
||||
}
|
||||
body .toolbar #globalScope:not(.on):hover {
|
||||
background-color: #999;
|
||||
border-color: #999;
|
||||
}
|
||||
body .toolbar .scopeRel {
|
||||
color: #24c;
|
||||
}
|
||||
body.globalScope .toolbar .scopeRel {
|
||||
body[data-scope="*"] .toolbar .scopeRel {
|
||||
color: #000;
|
||||
}
|
||||
body.globalScope .toolbar .scopeRel.disabled {
|
||||
body[data-scope="*"] .toolbar .scopeRel.disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
|
|
84
src/css/scope-selector.css
Normal file
84
src/css/scope-selector.css
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a browser extension to black/white list 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/uMatrix
|
||||
*/
|
||||
|
||||
.scope {
|
||||
background-color: #ccc;
|
||||
border: 1px solid #ccc;
|
||||
box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
display: inline-flex;
|
||||
color: white;
|
||||
margin: 0;
|
||||
padding: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.scope > span {
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
.scope > span > span {
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#specificScope {
|
||||
direction: ltr;
|
||||
justify-content: flex-end;
|
||||
width: 16em;
|
||||
}
|
||||
#specificScope.on {
|
||||
background-color: #24c;
|
||||
border-color: #24c;
|
||||
}
|
||||
#specificScope > span {
|
||||
background-color: #ccc;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
#specificScope > span.on {
|
||||
background-color: #24c;
|
||||
}
|
||||
#specificScope > span:first-of-type:not(.on):hover,
|
||||
#specificScope > span:first-of-type:not(.on):hover ~ span:not(.on),
|
||||
#specificScope > span:not(.on) + span:not(.on):hover,
|
||||
#specificScope > span:not(.on) + span:not(.on):hover ~ span:not(.on) {
|
||||
background-color: #999;
|
||||
}
|
||||
#specificScope > span:first-of-type:not(.on):hover ~ span,
|
||||
#specificScope > span:not(.on) + span:not(.on):hover ~ span,
|
||||
#specificScope > span.on + span:hover,
|
||||
#specificScope > span.on + span:hover ~ span {
|
||||
background-color: #139;
|
||||
}
|
||||
#specificScope > span:first-of-type {
|
||||
flex: 1;
|
||||
}
|
||||
#globalScope {
|
||||
justify-content: center;
|
||||
margin-left: 1px;
|
||||
width: 1.6em;
|
||||
}
|
||||
#globalScope.on {
|
||||
background-color: #000;
|
||||
border-color: #000;
|
||||
}
|
||||
#globalScope:not(.on):hover {
|
||||
background-color: #999;
|
||||
border-color: #999;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a browser extension to black/white list requests.
|
||||
Copyright (C) 2013-2018 Raymond Hill
|
||||
Copyright (C) 2013-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
|
||||
|
@ -101,11 +101,9 @@ api.fetchText = function(url, onLoad, onError) {
|
|||
|
||||
var onErrorReceived = function() {
|
||||
this.onload = this.onerror = this.ontimeout = null;
|
||||
µMatrix.logger.writeOne(
|
||||
'',
|
||||
'error',
|
||||
errorCantConnectTo.replace('{{url}}', actualUrl)
|
||||
);
|
||||
µMatrix.logger.writeOne({
|
||||
error: errorCantConnectTo.replace('{{url}}', actualUrl)
|
||||
});
|
||||
onError.call(null, { url: url, content: '' });
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a Chromium browser extension to black/white list requests.
|
||||
Copyright (C) 2015 Raymond Hill
|
||||
uMatrix - a browser extension to black/white list 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
|
||||
|
@ -19,14 +19,12 @@
|
|||
Home: https://github.com/gorhill/uMatrix
|
||||
*/
|
||||
|
||||
/* global µMatrix */
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Browser data jobs
|
||||
|
@ -50,7 +48,7 @@ var clearCache = function() {
|
|||
µm.browserCacheClearedCounter++;
|
||||
|
||||
// TODO: i18n
|
||||
µm.logger.writeOne('', 'info', vAPI.i18n('loggerEntryBrowserCacheCleared'));
|
||||
µm.logger.writeOne({ info: vAPI.i18n('loggerEntryBrowserCacheCleared') });
|
||||
|
||||
//console.debug('clearBrowserCacheCallback()> vAPI.browserData.clearCache() called');
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a browser extension to black/white list requests.
|
||||
Copyright (C) 2013-2018 Raymond Hill
|
||||
Copyright (C) 2013-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
|
||||
|
@ -210,7 +210,7 @@ var recordPageCookie = (function() {
|
|||
for ( let cookieKey of qentry[1] ) {
|
||||
let cookieEntry = cookieDict.get(cookieKey);
|
||||
if ( cookieEntry === undefined ) { continue; }
|
||||
let block = µm.mustBlock(
|
||||
let blocked = µm.mustBlock(
|
||||
pageStore.pageHostname,
|
||||
cookieEntry.hostname,
|
||||
'cookie'
|
||||
|
@ -224,17 +224,17 @@ var recordPageCookie = (function() {
|
|||
cookieLogEntryBuilder[4] =
|
||||
encodeURIComponent(cookieEntry.name);
|
||||
let cookieURL = cookieLogEntryBuilder.join('');
|
||||
pageStore.recordRequest('cookie', cookieURL, block);
|
||||
µm.logger.writeOne(
|
||||
pageStore.tabId,
|
||||
'net',
|
||||
pageStore.pageHostname,
|
||||
cookieURL,
|
||||
'cookie',
|
||||
block
|
||||
);
|
||||
pageStore.recordRequest('cookie', cookieURL, blocked);
|
||||
µm.logger.writeOne({
|
||||
tabId: pageStore.tabId,
|
||||
srcHn: pageStore.pageHostname,
|
||||
desHn: cookieEntry.hostname,
|
||||
desURL: cookieURL,
|
||||
type: 'cookie',
|
||||
blocked
|
||||
});
|
||||
cookieEntry.usedOn.add(pageStore.pageHostname);
|
||||
if ( !block ) { continue; }
|
||||
if ( !blocked ) { continue; }
|
||||
if ( µm.userSettings.deleteCookies ) {
|
||||
removeCookieAsync(cookieKey);
|
||||
}
|
||||
|
@ -288,9 +288,8 @@ var removeCookieAsync = function(cookieKey) {
|
|||
|
||||
var chromeCookieRemove = function(cookieEntry, name) {
|
||||
var url = cookieURLFromCookieEntry(cookieEntry);
|
||||
if ( url === '' ) {
|
||||
return;
|
||||
}
|
||||
if ( url === '' ) { return; }
|
||||
|
||||
var sessionCookieKey = cookieKeyFromCookieURL(url, 'session', name);
|
||||
var persistCookieKey = cookieKeyFromCookieURL(url, 'persistent', name);
|
||||
var callback = function(details) {
|
||||
|
@ -300,13 +299,17 @@ var chromeCookieRemove = function(cookieEntry, name) {
|
|||
if ( success ) {
|
||||
µm.cookieRemovedCounter += 1;
|
||||
}
|
||||
µm.logger.writeOne('', 'info', 'cookie', template.replace('{{value}}', sessionCookieKey));
|
||||
µm.logger.writeOne({
|
||||
info: template.replace('{{value}}', sessionCookieKey)
|
||||
});
|
||||
}
|
||||
if ( removeCookieFromDict(persistCookieKey) ) {
|
||||
if ( success ) {
|
||||
µm.cookieRemovedCounter += 1;
|
||||
}
|
||||
µm.logger.writeOne('', 'info', 'cookie', template.replace('{{value}}', persistCookieKey));
|
||||
µm.logger.writeOne({
|
||||
info: template.replace('{{value}}', persistCookieKey)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -549,7 +552,10 @@ vAPI.cookies.onChanged = (function() {
|
|||
vAPI.cookies.onRemoved = function(cookie) {
|
||||
var cookieKey = cookieKeyFromCookie(cookie);
|
||||
if ( removeCookieFromDict(cookieKey) ) {
|
||||
µm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey));
|
||||
µm.logger.writeOne({
|
||||
info: i18nCookieDeleteSuccess.replace('{{value}}', cookieKey),
|
||||
prettify: 'cookie'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -560,7 +566,10 @@ vAPI.cookies.onRemoved = function(cookie) {
|
|||
vAPI.cookies.onAllRemoved = function() {
|
||||
for ( var cookieKey of cookieDict.keys() ) {
|
||||
if ( removeCookieFromDict(cookieKey) ) {
|
||||
µm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey));
|
||||
µm.logger.writeOne({
|
||||
info: i18nCookieDeleteSuccess.replace('{{value}}', cookieKey),
|
||||
prettify: 'cookie'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a browser extension to benchmark browser session.
|
||||
Copyright (C) 2015-2018 Raymond Hill
|
||||
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
|
||||
|
@ -19,7 +19,7 @@
|
|||
Home: https://github.com/gorhill/sessbench
|
||||
*/
|
||||
|
||||
/* global uDom */
|
||||
/* global publicSuffixList, uDom, uMatrixScopeWidget */
|
||||
|
||||
'use strict';
|
||||
|
||||
|
@ -32,8 +32,8 @@
|
|||
var tbody = document.querySelector('#content tbody');
|
||||
var trJunkyard = [];
|
||||
var tdJunkyard = [];
|
||||
var firstVarDataCol = 2; // currently, column 2 (0-based index)
|
||||
var lastVarDataIndex = 3; // currently, d0-d3
|
||||
var firstVarDataCol = 1; // currently, column 2 (0-based index)
|
||||
var lastVarDataIndex = 4; // currently, 5 columns at most
|
||||
var maxEntries = 0;
|
||||
var noTabId = '';
|
||||
var pageStores = new Map();
|
||||
|
@ -41,7 +41,6 @@ var pageStoresToken;
|
|||
var ownerId = Date.now();
|
||||
|
||||
var emphasizeTemplate = document.querySelector('#emphasizeTemplate > span');
|
||||
var hiddenTemplate = document.querySelector('#hiddenTemplate > span');
|
||||
|
||||
var prettyRequestTypes = {
|
||||
'main_frame': 'doc',
|
||||
|
@ -67,14 +66,21 @@ document.getElementById('content').style.setProperty(
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var classNameFromTabId = function(tabId) {
|
||||
if ( tabId === noTabId ) {
|
||||
return 'tab_bts';
|
||||
let removeChildren = function(node) {
|
||||
while ( node.firstChild ) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
if ( tabId > 0 ) {
|
||||
return 'tab_' + tabId;
|
||||
};
|
||||
|
||||
let removeSelf = function(node) {
|
||||
let parent = node && node.parentNode;
|
||||
if ( parent ) {
|
||||
parent.removeChild(node);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
let prependChild = function(parent, child) {
|
||||
parent.insertBefore(child, parent.firstElementChild);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -158,21 +164,21 @@ var createCellAt = function(tr, index) {
|
|||
/******************************************************************************/
|
||||
|
||||
var createRow = function(layout) {
|
||||
var tr = trJunkyard.pop();
|
||||
let tr = trJunkyard.pop();
|
||||
if ( tr ) {
|
||||
tr.className = '';
|
||||
} else {
|
||||
tr = document.createElement('tr');
|
||||
}
|
||||
for ( var index = 0; index < firstVarDataCol; index++ ) {
|
||||
let index;
|
||||
for ( index = 0; index < firstVarDataCol; index++ ) {
|
||||
createCellAt(tr, index);
|
||||
}
|
||||
var i = 1, span = 1, td;
|
||||
let i = 1, span = 1;
|
||||
let td;
|
||||
for (;;) {
|
||||
td = createCellAt(tr, index);
|
||||
if ( i === lastVarDataIndex ) {
|
||||
break;
|
||||
}
|
||||
if ( i === lastVarDataIndex ) { break; }
|
||||
if ( layout.charAt(i) !== '1' ) {
|
||||
span += 1;
|
||||
} else {
|
||||
|
@ -188,22 +194,18 @@ var createRow = function(layout) {
|
|||
td.setAttribute('colspan', span);
|
||||
}
|
||||
index += 1;
|
||||
while ( (td = tr.cells[index]) ) {
|
||||
for (;;) {
|
||||
td = tr.cells[index];
|
||||
if ( !td ) { break; }
|
||||
tdJunkyard.push(tr.removeChild(td));
|
||||
}
|
||||
tr.removeAttribute('data-srchn');
|
||||
tr.removeAttribute('data-deshn');
|
||||
return tr;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var createHiddenTextNode = function(text) {
|
||||
var node = hiddenTemplate.cloneNode(true);
|
||||
node.textContent = text;
|
||||
return node;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var padTo2 = function(v) {
|
||||
return v < 10 ? '0' + v : v;
|
||||
};
|
||||
|
@ -223,66 +225,84 @@ var createGap = function(tabId, url) {
|
|||
/******************************************************************************/
|
||||
|
||||
var renderLogEntry = function(entry) {
|
||||
var tr;
|
||||
var fvdc = firstVarDataCol;
|
||||
let details;
|
||||
try {
|
||||
details = JSON.parse(entry.details);
|
||||
} catch(ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
if ( details instanceof Object === false ) { return; }
|
||||
|
||||
switch ( entry.cat ) {
|
||||
case 'error':
|
||||
case 'info':
|
||||
let tr;
|
||||
let fvdc = firstVarDataCol;
|
||||
|
||||
if ( details.error !== undefined ) {
|
||||
tr = createRow('1');
|
||||
if ( entry.d0 === 'cookie' ) {
|
||||
tr.cells[fvdc].appendChild(emphasizeCookie(entry.d1));
|
||||
tr.classList.add('cat_error');
|
||||
tr.cells[fvdc].textContent = details.error;
|
||||
} else if ( details.info !== undefined ) {
|
||||
tr = createRow('1');
|
||||
tr.classList.add('cat_info');
|
||||
if ( details.prettify === 'cookie' ) {
|
||||
tr.cells[fvdc].appendChild(emphasizeCookie(details.info));
|
||||
} else {
|
||||
tr.cells[fvdc].textContent = entry.d0;
|
||||
tr.cells[fvdc].textContent = details.info;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'net':
|
||||
tr = createRow('111');
|
||||
} else if ( details.srcHn !== undefined && details.desHn !== undefined ) {
|
||||
tr = createRow('1111');
|
||||
tr.classList.add('canMtx');
|
||||
tr.classList.add('cat_net');
|
||||
tr.setAttribute('data-srchn', details.srcHn);
|
||||
tr.setAttribute('data-deshn', details.desHn);
|
||||
tr.setAttribute('data-type', details.type);
|
||||
// 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 ( entry.d2 === 'doc' && entry.tab !== noTabId ) {
|
||||
createGap(entry.tab, entry.d1);
|
||||
if ( details.type === 'doc' && details.tabId !== noTabId ) {
|
||||
createGap(details.tabId, details.desURL);
|
||||
}
|
||||
if ( entry.d3 ) {
|
||||
tr.cells[fvdc+0].textContent = details.srcHn;
|
||||
if ( details.blocked ) {
|
||||
tr.classList.add('blocked');
|
||||
tr.cells[fvdc].textContent = '--';
|
||||
tr.cells[fvdc+1].textContent = '--';
|
||||
} else {
|
||||
tr.cells[fvdc].textContent = '';
|
||||
tr.cells[fvdc+1].textContent = '';
|
||||
}
|
||||
tr.cells[fvdc+1].textContent = (prettyRequestTypes[entry.d2] || entry.d2);
|
||||
if ( dontEmphasizeSet.has(entry.d2) ) {
|
||||
tr.cells[fvdc+2].textContent = entry.d1;
|
||||
} else if ( entry.d2 === 'cookie' ) {
|
||||
tr.cells[fvdc+2].appendChild(emphasizeCookie(entry.d1));
|
||||
tr.cells[fvdc+2].textContent = (prettyRequestTypes[details.type] || details.type);
|
||||
if ( dontEmphasizeSet.has(details.type) ) {
|
||||
tr.cells[fvdc+3].textContent = details.desURL;
|
||||
} else {
|
||||
tr.cells[fvdc+2].appendChild(emphasizeHostname(entry.d1));
|
||||
tr.cells[fvdc+3].appendChild(emphasizeHostname(details.desURL));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
} else if ( details.header ) {
|
||||
tr = createRow('1111');
|
||||
tr.classList.add('canMtx');
|
||||
tr.classList.add('cat_net');
|
||||
tr.cells[fvdc+0].textContent = details.srcHn || '';
|
||||
if ( details.change === -1 ) {
|
||||
tr.classList.add('blocked');
|
||||
tr.cells[fvdc+1].textContent = '--';
|
||||
} else {
|
||||
tr.cells[fvdc+1].textContent = '';
|
||||
}
|
||||
tr.cells[fvdc+2].textContent = details.header.name;
|
||||
tr.cells[fvdc+3].textContent = details.header.value;
|
||||
} else {
|
||||
tr = createRow('1');
|
||||
tr.cells[fvdc].textContent = entry.d0;
|
||||
break;
|
||||
tr.cells[fvdc].textContent = 'huh?';
|
||||
}
|
||||
|
||||
// Fields common to all rows.
|
||||
var time = logDate;
|
||||
let time = logDate;
|
||||
time.setTime(entry.tstamp - logDateTimezoneOffset);
|
||||
tr.cells[0].textContent = padTo2(time.getUTCHours()) + ':' +
|
||||
padTo2(time.getUTCMinutes()) + ':' +
|
||||
padTo2(time.getSeconds());
|
||||
|
||||
if ( entry.tab ) {
|
||||
if ( details.tabId ) {
|
||||
tr.classList.add('tab');
|
||||
tr.classList.add(classNameFromTabId(entry.tab));
|
||||
if ( entry.tab === noTabId ) {
|
||||
tr.cells[1].appendChild(createHiddenTextNode('bts'));
|
||||
}
|
||||
}
|
||||
if ( entry.cat !== '' ) {
|
||||
tr.classList.add('cat_' + entry.cat);
|
||||
tr.setAttribute('data-tabid', details.tabId);
|
||||
} else {
|
||||
tr.removeAttribute('data-tabid');
|
||||
}
|
||||
|
||||
rowFilterer.filterOne(tr, true);
|
||||
|
@ -297,18 +317,13 @@ var logDate = new Date(),
|
|||
/******************************************************************************/
|
||||
|
||||
var renderLogEntries = function(response) {
|
||||
var entries = response.entries;
|
||||
let entries = response.entries;
|
||||
if ( entries.length === 0 ) { return; }
|
||||
|
||||
// Preserve scroll position
|
||||
var height = tbody.offsetHeight;
|
||||
let height = tbody.offsetHeight;
|
||||
|
||||
var n = entries.length;
|
||||
var entry;
|
||||
for ( var i = 0; i < n; i++ ) {
|
||||
entry = entries[i];
|
||||
// Unlikely, but it may happen
|
||||
if ( entry.tab && pageStores.has(entry.tab) === false ) { continue; }
|
||||
for ( let i = 0, n = entries.length; i < n; i++ ) {
|
||||
renderLogEntry(entries[i]);
|
||||
}
|
||||
|
||||
|
@ -317,10 +332,8 @@ var renderLogEntries = function(response) {
|
|||
// dynamically refreshed pages.
|
||||
truncateLog(maxEntries);
|
||||
|
||||
var yDelta = tbody.offsetHeight - height;
|
||||
if ( yDelta === 0 ) {
|
||||
return;
|
||||
}
|
||||
let yDelta = tbody.offsetHeight - height;
|
||||
if ( yDelta === 0 ) { return; }
|
||||
|
||||
// Chromium:
|
||||
// body.scrollTop = good value
|
||||
|
@ -333,7 +346,7 @@ var renderLogEntries = function(response) {
|
|||
// Firefox:
|
||||
// body.scrollTop = 0
|
||||
// body.parentNode.scrollTop = good value
|
||||
var parentNode = document.body.parentNode;
|
||||
let parentNode = document.body.parentNode;
|
||||
if ( parentNode && parentNode.scrollTop !== 0 ) {
|
||||
parentNode.scrollTop += yDelta;
|
||||
}
|
||||
|
@ -357,10 +370,6 @@ var synchronizeTabIds = function(newPageStores) {
|
|||
trs.removeClass('canMtx');
|
||||
rowVoided = true;
|
||||
}
|
||||
// Remove popup if it is currently bound to a removed tab.
|
||||
if ( tabId === popupManager.tabId ) {
|
||||
popupManager.toggleOff();
|
||||
}
|
||||
}
|
||||
|
||||
var select = document.getElementById('pageSelector');
|
||||
|
@ -379,7 +388,7 @@ var synchronizeTabIds = function(newPageStores) {
|
|||
select.appendChild(option);
|
||||
}
|
||||
option.textContent = newPageStores.get(tabId);
|
||||
option.value = classNameFromTabId(tabId);
|
||||
option.value = tabId;
|
||||
if ( option.value === selectValue ) {
|
||||
option.setAttribute('selected', '');
|
||||
} else {
|
||||
|
@ -487,22 +496,19 @@ var readLogBufferAsync = function() {
|
|||
/******************************************************************************/
|
||||
|
||||
var pageSelectorChanged = function() {
|
||||
var style = document.getElementById('tabFilterer');
|
||||
var tabClass = document.getElementById('pageSelector').value;
|
||||
var sheet = style.sheet;
|
||||
let style = document.getElementById('tabFilterer');
|
||||
let tabId = document.getElementById('pageSelector').value;
|
||||
let sheet = style.sheet;
|
||||
while ( sheet.cssRules.length !== 0 ) {
|
||||
sheet.deleteRule(0);
|
||||
}
|
||||
if ( tabClass !== '' ) {
|
||||
if ( tabId.length !== 0 ) {
|
||||
sheet.insertRule(
|
||||
'#content table tr:not(.' + tabClass + ') { display: none; }',
|
||||
'#content table tr:not([data-tabid="' + tabId + '"]) { display: none; }',
|
||||
0
|
||||
);
|
||||
}
|
||||
uDom('#refresh').toggleClass(
|
||||
'disabled',
|
||||
tabClass === '' || tabClass === 'tab_bts'
|
||||
);
|
||||
uDom('#refresh').toggleClass('disabled', /^\d+$/.test(tabId) === false);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -678,6 +684,285 @@ var rowFilterer = (function() {
|
|||
};
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
var ruleEditor = (function() {
|
||||
let ruleEditorNode = document.getElementById('ruleEditor');
|
||||
let ruleActionPicker = document.getElementById('ruleActionPicker');
|
||||
let listeners = [];
|
||||
|
||||
let addListener = function(node, type, handler, bits) {
|
||||
let options;
|
||||
if ( typeof bits === 'number' && (bits & 0b11) !== 0 ) {
|
||||
options = {};
|
||||
if ( bits & 0b01 ) {
|
||||
options.capture = true;
|
||||
}
|
||||
if ( bits & 0b10 ) {
|
||||
options.passive = true;
|
||||
}
|
||||
}
|
||||
listeners.push({ node, type, handler, options });
|
||||
return node.addEventListener(type, handler, options);
|
||||
};
|
||||
|
||||
let setup = function(details) {
|
||||
ruleEditorNode.setAttribute('data-tabid', details.tabId);
|
||||
ruleEditorNode.classList.toggle(
|
||||
'colorblind',
|
||||
details.options.colorBlindFriendly === true
|
||||
);
|
||||
|
||||
// Initialize scope selector
|
||||
let srcDn = domainFromSrcHostname(details.srcHn);
|
||||
let scope = details.options.popupScopeLevel === '*' ?
|
||||
'*' :
|
||||
details.options.popupScopeLevel === 'domain' ?
|
||||
srcDn :
|
||||
details.srcHn;
|
||||
uMatrixScopeWidget.init(srcDn, details.srcHn, scope, ruleEditorNode);
|
||||
|
||||
// Create rule rows
|
||||
let ruleWidgets = ruleEditorNode.querySelector('.ruleWidgets');
|
||||
removeChildren(ruleWidgets);
|
||||
let ruleWidgetTemplate =
|
||||
document.querySelector('#ruleRowTemplate .ruleRow');
|
||||
|
||||
// Rules: specific to desHn, from broadest to narrowest
|
||||
let desHn = details.desHn;
|
||||
let desDn = domainFromDesHostname(desHn);
|
||||
for (;;) {
|
||||
let ruleRow = ruleWidgetTemplate.cloneNode(true);
|
||||
ruleRow.setAttribute('data-deshn', desHn);
|
||||
ruleRow.children[0].textContent = desHn;
|
||||
ruleRow.children[1].setAttribute('data-type', details.type);
|
||||
if ( desHn === details.desHn ) {
|
||||
ruleRow.children[1].textContent = '1';
|
||||
}
|
||||
prependChild(ruleWidgets, ruleRow);
|
||||
if ( desHn === desDn ) { break; }
|
||||
let pos = desHn.indexOf('.');
|
||||
if ( pos === -1 ) { break; }
|
||||
desHn = desHn.slice(pos + 1);
|
||||
}
|
||||
|
||||
// Rules: 1st-party, if needed
|
||||
if ( desDn === srcDn ) {
|
||||
let ruleRow = ruleWidgetTemplate.cloneNode(true);
|
||||
ruleRow.setAttribute('data-deshn', '1st-party');
|
||||
ruleRow.children[0].textContent = '1st-party';
|
||||
ruleRow.children[1].setAttribute('data-type', details.type);
|
||||
prependChild(ruleWidgets, ruleRow);
|
||||
}
|
||||
|
||||
// Rules: unspecific
|
||||
{
|
||||
let ruleRow = ruleWidgetTemplate.cloneNode(true);
|
||||
ruleRow.setAttribute('data-deshn', '*');
|
||||
ruleRow.children[0].textContent = 'all';
|
||||
ruleRow.children[1].setAttribute('data-type', details.type);
|
||||
ruleRow.children[1].textContent = details.type;
|
||||
prependChild(ruleWidgets, ruleRow);
|
||||
}
|
||||
|
||||
colorize();
|
||||
|
||||
addListener(ruleEditorNode, 'click', quitHandler, 0b01);
|
||||
addListener(window, 'uMatrixScopeWidgetChange', scopeChangeHandler);
|
||||
addListener(ruleWidgets, 'mouseenter', attachRulePicker, 0b11);
|
||||
addListener(ruleWidgets, 'mouseleave', removeRulePicker, 0b11);
|
||||
addListener(ruleActionPicker, 'click', rulePickerHandler, 0b11);
|
||||
addListener(ruleEditorNode.querySelector('.buttonReload'), 'click', reload);
|
||||
addListener(ruleEditorNode.querySelector('.buttonRevertScope'), 'click', revert);
|
||||
addListener(ruleEditorNode.querySelector('.buttonPersist'), 'click', persist);
|
||||
|
||||
document.body.appendChild(ruleEditorNode);
|
||||
};
|
||||
|
||||
let colorize = function() {
|
||||
let srcHn = uMatrixScopeWidget.getScope();
|
||||
let ruleCells = ruleEditorNode.querySelectorAll('.ruleCell');
|
||||
let ruleParts = [];
|
||||
for ( let ruleCell of ruleCells ) {
|
||||
ruleParts.push(
|
||||
srcHn,
|
||||
ruleCell.closest('.ruleRow').getAttribute('data-deshn'),
|
||||
ruleCell.getAttribute('data-type')
|
||||
);
|
||||
}
|
||||
vAPI.messaging.send(
|
||||
'default',
|
||||
{ what: 'getCellColors', ruleParts },
|
||||
response => {
|
||||
let tColors = response.tColors,
|
||||
pColors = response.pColors,
|
||||
diffCount = 0;
|
||||
for ( let i = 0; i < ruleCells.length; i++ ) {
|
||||
let ruleCell = ruleCells[i];
|
||||
let tColor = tColors[i];
|
||||
let pColor = pColors[i];
|
||||
ruleCell.setAttribute('data-tcolor', tColor);
|
||||
ruleCell.setAttribute('data-pcolor', pColor);
|
||||
if ( tColor === pColor ) { continue; }
|
||||
if ( tColor < 128 && pColor < 128 ) { continue; }
|
||||
diffCount += 1;
|
||||
}
|
||||
let dirty = diffCount !== 0;
|
||||
ruleEditorNode
|
||||
.querySelector('.buttonPersist .badge')
|
||||
.textContent = dirty ? diffCount : '';
|
||||
ruleEditorNode
|
||||
.querySelector('.buttonRevertScope')
|
||||
.classList
|
||||
.toggle('disabled', !dirty);
|
||||
ruleEditorNode
|
||||
.querySelector('.buttonPersist')
|
||||
.classList
|
||||
.toggle('disabled', !dirty);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
let quitHandler = function(ev) {
|
||||
let target = ev.target;
|
||||
if ( target.classList.contains('modalDialog') ) {
|
||||
stop();
|
||||
}
|
||||
};
|
||||
|
||||
let scopeChangeHandler = function() {
|
||||
colorize();
|
||||
};
|
||||
|
||||
let attachRulePicker = function(ev) {
|
||||
let target = ev.target;
|
||||
if (
|
||||
target instanceof HTMLElement === false ||
|
||||
target.classList.contains('ruleCell') === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
target.appendChild(ruleActionPicker);
|
||||
};
|
||||
|
||||
let removeRulePicker = function(ev) {
|
||||
let target = ev.target;
|
||||
if (
|
||||
target instanceof HTMLElement === false ||
|
||||
ruleActionPicker.closest('.ruleCell') === target.closest('.ruleCell')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
removeSelf(ruleActionPicker);
|
||||
};
|
||||
|
||||
let rulePickerHandler = function(ev) {
|
||||
let action = ev.target.className;
|
||||
if ( action !== 'allowRule' && action !== 'blockRule' ) { return; }
|
||||
let cell = ev.target.closest('.ruleCell');
|
||||
if ( cell === null ) { return; }
|
||||
let row = cell.closest('.ruleRow');
|
||||
let desHn = row.getAttribute('data-deshn');
|
||||
let type = cell.getAttribute('data-type');
|
||||
let color = parseInt(cell.getAttribute('data-tcolor'), 10);
|
||||
let what;
|
||||
if ( color === 1 || color === 2 ) {
|
||||
what = action === 'blockRule' ?
|
||||
'blacklistMatrixCell' :
|
||||
'whitelistMatrixCell';
|
||||
} else if ( desHn === '*' && type === '*' ) {
|
||||
what = color === 130 ?
|
||||
'blacklistMatrixCell' :
|
||||
'whitelistMatrixCell';
|
||||
} else {
|
||||
what = 'graylistMatrixCell';
|
||||
}
|
||||
let request = {
|
||||
what,
|
||||
srcHostname: uMatrixScopeWidget.getScope(),
|
||||
desHostname: desHn,
|
||||
type
|
||||
};
|
||||
vAPI.messaging.send('default', request, colorize);
|
||||
};
|
||||
|
||||
|
||||
let reload = function(ev) {
|
||||
vAPI.messaging.send('default', {
|
||||
what: 'forceReloadTab',
|
||||
tabId: parseInt(ruleEditorNode.getAttribute('data-tabid'), 10),
|
||||
bypassCache: ev && (ev.ctrlKey || ev.metaKey || ev.shiftKey)
|
||||
});
|
||||
};
|
||||
|
||||
let diff = function() {
|
||||
let entries = [];
|
||||
let cells = ruleEditorNode.querySelectorAll('.ruleCell');
|
||||
let srcHn = uMatrixScopeWidget.getScope();
|
||||
for ( let cell of cells ) {
|
||||
let tColor = cell.getAttribute('data-tcolor');
|
||||
let pColor = cell.getAttribute('data-pcolor');
|
||||
if ( tColor === pColor || tColor < 128 && pColor < 128 ) {
|
||||
continue;
|
||||
}
|
||||
let row = cell.closest('.ruleRow');
|
||||
entries.push({
|
||||
srcHn,
|
||||
desHn: row.getAttribute('data-deshn'),
|
||||
type: cell.getAttribute('data-type')
|
||||
});
|
||||
}
|
||||
return entries;
|
||||
};
|
||||
|
||||
let persist = function() {
|
||||
let entries = diff();
|
||||
if ( entries.length === 0 ) { return; }
|
||||
vAPI.messaging.send(
|
||||
'default',
|
||||
{ what: 'rulesetPersist', entries },
|
||||
colorize
|
||||
);
|
||||
};
|
||||
|
||||
let revert = function() {
|
||||
let entries = diff();
|
||||
if ( entries.length === 0 ) { return; }
|
||||
vAPI.messaging.send(
|
||||
'default',
|
||||
{ what: 'rulesetRevert', entries },
|
||||
colorize
|
||||
);
|
||||
};
|
||||
|
||||
let start = function(ev) {
|
||||
let targetRow = ev.target.parentElement;
|
||||
let srcHn = targetRow.getAttribute('data-srchn') || '';
|
||||
let desHn = targetRow.getAttribute('data-deshn') || '';
|
||||
let type = targetRow.getAttribute('data-type') || '';
|
||||
if ( srcHn === '' || desHn === '' || type === '' ) { return; }
|
||||
let tabId = parseInt(targetRow.getAttribute('data-tabid'), 10);
|
||||
|
||||
vAPI.messaging.send(
|
||||
'logger-ui.js',
|
||||
{ what: 'getRuleEditorOptions' },
|
||||
options => { setup({ tabId, srcHn, desHn, type, options }); }
|
||||
);
|
||||
};
|
||||
|
||||
let stop = function() {
|
||||
for ( let { node, type, handler, options } of listeners ) {
|
||||
node.removeEventListener(type, handler, options);
|
||||
}
|
||||
listeners = [];
|
||||
ruleEditorNode.querySelector('.buttonReload').removeEventListener('click', reload);
|
||||
removeSelf(ruleEditorNode);
|
||||
};
|
||||
|
||||
return { start, stop };
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var toJunkyard = function(trs) {
|
||||
|
@ -725,140 +1010,6 @@ var toggleCompactRow = function(ev) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var popupManager = (function() {
|
||||
var realTabId = null;
|
||||
var localTabId = null;
|
||||
var container = null;
|
||||
var popup = null;
|
||||
var popupObserver = null;
|
||||
var style = null;
|
||||
var styleTemplate = [
|
||||
'tr:not(.tab_{{tabId}}) {',
|
||||
'cursor: not-allowed;',
|
||||
'opacity: 0.2;',
|
||||
'}'
|
||||
].join('\n');
|
||||
|
||||
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');
|
||||
}
|
||||
popup.style.removeProperty('height');
|
||||
if ( popupBody.clientHeight !== 0 && popup.clientHeight !== popupBody.clientHeight ) {
|
||||
popup.style.setProperty('height', popupBody.clientHeight + 'px');
|
||||
}
|
||||
var ph = document.documentElement.clientHeight;
|
||||
var crect = container.getBoundingClientRect();
|
||||
if ( crect.height > ph ) {
|
||||
popup.style.setProperty('height', 'calc(' + ph + 'px - 1.8em)');
|
||||
}
|
||||
// Adjust width for presence/absence of vertical scroll bar which may
|
||||
// have appeared as a result of last operation.
|
||||
var cw = container.clientWidth;
|
||||
var dw = popup.contentWindow.document.documentElement.clientWidth;
|
||||
if ( cw !== dw ) {
|
||||
container.style.setProperty('width', (2 * cw - dw) + 'px');
|
||||
}
|
||||
};
|
||||
|
||||
var toggleSize = function() {
|
||||
container.classList.toggle('hide');
|
||||
};
|
||||
|
||||
var onResizeRequested = function() {
|
||||
var popupBody = popup.contentWindow.document.body;
|
||||
if ( popupBody.hasAttribute('data-resize-popup') === false ) {
|
||||
return;
|
||||
}
|
||||
popupBody.removeAttribute('data-resize-popup');
|
||||
resizePopup();
|
||||
};
|
||||
|
||||
var onLoad = function() {
|
||||
resizePopup();
|
||||
var popupBody = popup.contentDocument.body;
|
||||
popupBody.removeAttribute('data-resize-popup');
|
||||
popupObserver.observe(popupBody, {
|
||||
attributes: true,
|
||||
attributesFilter: [ 'data-resize-popup' ]
|
||||
});
|
||||
};
|
||||
|
||||
var toggleOn = function(td) {
|
||||
var tr = td.parentNode;
|
||||
var matches = tr.className.match(/(?:^| )tab_([^ ]+)/);
|
||||
if ( matches === null ) {
|
||||
return;
|
||||
}
|
||||
realTabId = localTabId = matches[1];
|
||||
if ( localTabId === 'bts' ) {
|
||||
realTabId = noTabId;
|
||||
}
|
||||
|
||||
container = document.getElementById('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(onResizeRequested);
|
||||
container.appendChild(popup);
|
||||
|
||||
style = document.getElementById('popupFilterer');
|
||||
style.textContent = styleTemplate.replace('{{tabId}}', localTabId);
|
||||
|
||||
document.body.classList.add('popupOn');
|
||||
};
|
||||
|
||||
var toggleOff = function() {
|
||||
document.body.classList.remove('popupOn');
|
||||
|
||||
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');
|
||||
|
||||
popup.removeEventListener('load', onLoad);
|
||||
popupObserver.disconnect();
|
||||
popupObserver = null;
|
||||
popup.setAttribute('src', '');
|
||||
container.removeChild(popup);
|
||||
popup = null;
|
||||
|
||||
style.textContent = '';
|
||||
style = null;
|
||||
|
||||
container = null;
|
||||
realTabId = null;
|
||||
};
|
||||
|
||||
var exports = {
|
||||
toggleOn: function(ev) {
|
||||
if ( realTabId === null ) {
|
||||
toggleOn(ev.target);
|
||||
}
|
||||
},
|
||||
toggleOff: function() {
|
||||
if ( realTabId !== null ) {
|
||||
toggleOff();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Object.defineProperty(exports, 'tabId', {
|
||||
get: function() { return realTabId || 0; }
|
||||
});
|
||||
|
||||
return exports;
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var grabView = function() {
|
||||
if ( ownerId === undefined ) {
|
||||
ownerId = Date.now();
|
||||
|
@ -882,6 +1033,40 @@ window.addEventListener('beforeunload', releaseView);
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
// We will lookup domains locally.
|
||||
|
||||
let domainFromSrcHostname = (function() {
|
||||
let srcHn = '', srcDn = '';
|
||||
return function(hn) {
|
||||
if ( hn !== srcHn ) {
|
||||
srcHn = hn;
|
||||
srcDn = publicSuffixList.getDomain(hn);
|
||||
}
|
||||
return srcDn;
|
||||
};
|
||||
})();
|
||||
|
||||
let domainFromDesHostname = (function() {
|
||||
let desHn = '', desDn = '';
|
||||
return function(hn) {
|
||||
if ( hn !== desHn ) {
|
||||
desHn = hn;
|
||||
desDn = publicSuffixList.getDomain(hn);
|
||||
}
|
||||
return desDn;
|
||||
};
|
||||
})();
|
||||
|
||||
vAPI.messaging.send(
|
||||
'logger-ui.js',
|
||||
{ what: 'getPublicSuffixListData' },
|
||||
response => {
|
||||
publicSuffixList.fromSelfie(response);
|
||||
}
|
||||
);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
readLogBuffer();
|
||||
|
||||
uDom('#pageSelector').on('change', pageSelectorChanged);
|
||||
|
@ -891,7 +1076,7 @@ uDom('#clean').on('click', cleanBuffer);
|
|||
uDom('#clear').on('click', clearBuffer);
|
||||
uDom('#maxEntries').on('change', onMaxEntriesChanged);
|
||||
uDom('#content table').on('click', 'tr > td:nth-of-type(1)', toggleCompactRow);
|
||||
uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(2)', popupManager.toggleOn);
|
||||
uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(3)', ruleEditor.start);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a browser extension to block requests.
|
||||
Copyright (C) 2015-2017 Raymond Hill
|
||||
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,29 +26,24 @@
|
|||
|
||||
µMatrix.logger = (function() {
|
||||
|
||||
var LogEntry = function(args) {
|
||||
this.init(args);
|
||||
let LogEntry = function(details) {
|
||||
this.init(details);
|
||||
};
|
||||
|
||||
LogEntry.prototype.init = function(args) {
|
||||
LogEntry.prototype.init = function(details) {
|
||||
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.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;
|
||||
let logBufferObsoleteAfter = 30 * 1000;
|
||||
|
||||
var janitor = function() {
|
||||
let janitor = function() {
|
||||
if (
|
||||
buffer !== null &&
|
||||
lastReadTime < (Date.now() - logBufferObsoleteAfter)
|
||||
|
@ -56,34 +51,37 @@
|
|||
buffer = null;
|
||||
writePtr = 0;
|
||||
api.ownerId = undefined;
|
||||
api.enabled = false;
|
||||
}
|
||||
if ( buffer !== null ) {
|
||||
vAPI.setTimeout(janitor, logBufferObsoleteAfter);
|
||||
}
|
||||
};
|
||||
|
||||
var api = {
|
||||
let 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;
|
||||
this.enabled = true;
|
||||
if ( buffer === null ) {
|
||||
buffer = [];
|
||||
vAPI.setTimeout(janitor, logBufferObsoleteAfter);
|
||||
}
|
||||
var out = buffer.slice(0, writePtr);
|
||||
let out = buffer.slice(0, writePtr);
|
||||
writePtr = 0;
|
||||
lastReadTime = Date.now();
|
||||
return out;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return api;
|
||||
|
|
|
@ -509,8 +509,8 @@ Matrix.prototype.evaluateCellZXY = function(srcHostname, desHostname, type) {
|
|||
/******************************************************************************/
|
||||
|
||||
Matrix.prototype.evaluateRowZXY = function(srcHostname, desHostname) {
|
||||
var out = [];
|
||||
for ( var type of typeBitOffsets.keys() ) {
|
||||
let out = [];
|
||||
for ( let type of typeBitOffsets.keys() ) {
|
||||
out.push(this.evaluateCellZXY(srcHostname, desHostname, type));
|
||||
}
|
||||
return out;
|
||||
|
@ -846,6 +846,33 @@ Matrix.prototype.applyDiff = function(diff, from) {
|
|||
return changed;
|
||||
};
|
||||
|
||||
Matrix.prototype.copyRuleset = function(entries, from, deep) {
|
||||
let changed = false;
|
||||
for ( let entry of entries ) {
|
||||
let srcHn = entry.srcHn;
|
||||
for (;;) {
|
||||
if (
|
||||
entry.switchName !== undefined &&
|
||||
switchBitOffsets.has(entry.switchName)
|
||||
) {
|
||||
let val = from.evaluateSwitch(entry.switchName, srcHn);
|
||||
if ( this.setSwitch(entry.switchName, srcHn, val) ) {
|
||||
changed = true;
|
||||
}
|
||||
} else if ( entry.desHn && entry.type ) {
|
||||
let val = from.evaluateCell(srcHn, entry.desHn, entry.type);
|
||||
if ( this.setCell(srcHn, entry.desHn, entry.type, val) ) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if ( !deep ) { break; }
|
||||
srcHn = toBroaderHostname(srcHn);
|
||||
if ( srcHn === '' ) { break; }
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
return Matrix;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
Home: https://github.com/gorhill/uMatrix
|
||||
*/
|
||||
|
||||
/* globals publicSuffixList */
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -53,6 +55,14 @@ function onMessage(request, sender, callback) {
|
|||
var response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'blacklistMatrixCell':
|
||||
µm.tMatrix.blacklistCell(
|
||||
request.srcHostname,
|
||||
request.desHostname,
|
||||
request.type
|
||||
);
|
||||
break;
|
||||
|
||||
case 'forceReloadTab':
|
||||
µm.forceReload(request.tabId, request.bypassCache);
|
||||
break;
|
||||
|
@ -62,6 +72,25 @@ function onMessage(request, sender, callback) {
|
|||
µm.assets.updateStart({ delay: 2000 });
|
||||
break;
|
||||
|
||||
case 'getCellColors':
|
||||
let ruleParts = request.ruleParts;
|
||||
let tColors = [];
|
||||
let pColors = [];
|
||||
for ( let i = 0, n = ruleParts.length; i < n; i += 3 ) {
|
||||
tColors.push(µm.tMatrix.evaluateCellZXY(
|
||||
ruleParts[i+0],
|
||||
ruleParts[i+1],
|
||||
ruleParts[i+2]
|
||||
));
|
||||
pColors.push(µm.pMatrix.evaluateCellZXY(
|
||||
ruleParts[i+0],
|
||||
ruleParts[i+1],
|
||||
ruleParts[i+2]
|
||||
));
|
||||
}
|
||||
response = { tColors, pColors };
|
||||
break;
|
||||
|
||||
case 'getUserSettings':
|
||||
response = {
|
||||
userSettings: µm.userSettings,
|
||||
|
@ -81,6 +110,14 @@ function onMessage(request, sender, callback) {
|
|||
µm.gotoURL(request);
|
||||
break;
|
||||
|
||||
case 'graylistMatrixCell':
|
||||
µm.tMatrix.graylistCell(
|
||||
request.srcHostname,
|
||||
request.desHostname,
|
||||
request.type
|
||||
);
|
||||
break;
|
||||
|
||||
case 'mustBlock':
|
||||
response = µm.mustBlock(
|
||||
request.scope,
|
||||
|
@ -89,6 +126,16 @@ function onMessage(request, sender, callback) {
|
|||
);
|
||||
break;
|
||||
|
||||
case 'rulesetRevert':
|
||||
µm.tMatrix.copyRuleset(request.entries, µm.pMatrix, true);
|
||||
break;
|
||||
|
||||
case 'rulesetPersist':
|
||||
if ( µm.pMatrix.copyRuleset(request.entries, µm.tMatrix, true) ) {
|
||||
µm.saveMatrix();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'readRawSettings':
|
||||
response = µm.stringFromRawSettings();
|
||||
break;
|
||||
|
@ -115,6 +162,14 @@ function onMessage(request, sender, callback) {
|
|||
response = µm.changeUserSettings(request.name, request.value);
|
||||
break;
|
||||
|
||||
case 'whitelistMatrixCell':
|
||||
µm.tMatrix.whitelistCell(
|
||||
request.srcHostname,
|
||||
request.desHostname,
|
||||
request.type
|
||||
);
|
||||
break;
|
||||
|
||||
case 'writeRawSettings':
|
||||
µm.rawSettingsFromString(request.content);
|
||||
break;
|
||||
|
@ -366,30 +421,6 @@ var onMessage = function(request, sender, callback) {
|
|||
);
|
||||
break;
|
||||
|
||||
case 'blacklistMatrixCell':
|
||||
µm.tMatrix.blacklistCell(
|
||||
request.srcHostname,
|
||||
request.desHostname,
|
||||
request.type
|
||||
);
|
||||
break;
|
||||
|
||||
case 'whitelistMatrixCell':
|
||||
µm.tMatrix.whitelistCell(
|
||||
request.srcHostname,
|
||||
request.desHostname,
|
||||
request.type
|
||||
);
|
||||
break;
|
||||
|
||||
case 'graylistMatrixCell':
|
||||
µm.tMatrix.graylistCell(
|
||||
request.srcHostname,
|
||||
request.desHostname,
|
||||
request.type
|
||||
);
|
||||
break;
|
||||
|
||||
case 'applyDiffToPermanentMatrix': // aka "persist"
|
||||
if ( µm.pMatrix.applyDiff(request.diff, µm.tMatrix) ) {
|
||||
µm.saveMatrix();
|
||||
|
@ -429,44 +460,44 @@ var µm = µMatrix;
|
|||
var foundInlineCode = function(tabId, pageStore, details, type) {
|
||||
if ( pageStore === null ) { return; }
|
||||
|
||||
var pageHostname = pageStore.pageHostname,
|
||||
let srcHn = pageStore.pageHostname,
|
||||
µmuri = µm.URI.set(details.documentURI),
|
||||
desHn = µmuri.hostname,
|
||||
frameURL = µmuri.normalizedURI();
|
||||
|
||||
var blocked = details.blocked;
|
||||
let blocked = details.blocked;
|
||||
if ( blocked === undefined ) {
|
||||
blocked = µm.mustBlock(pageHostname, µmuri.hostname, type);
|
||||
blocked = µm.mustBlock(srcHn, desHn, type);
|
||||
}
|
||||
|
||||
var mapTo = {
|
||||
let mapTo = {
|
||||
css: 'style',
|
||||
script: 'script'
|
||||
};
|
||||
|
||||
// https://github.com/gorhill/httpswitchboard/issues/333
|
||||
// Look-up here whether inline scripting is blocked for the frame.
|
||||
var url = frameURL + '{inline_' + mapTo[type] + '}';
|
||||
pageStore.recordRequest(type, url, blocked);
|
||||
µm.logger.writeOne(tabId, 'net', pageHostname, url, type, blocked);
|
||||
// Look-up here whether inline scripting is blocked for the frame.
|
||||
let desURL = frameURL + '{inline_' + mapTo[type] + '}';
|
||||
pageStore.recordRequest(type, desURL, blocked);
|
||||
µm.logger.writeOne({ tabId, srcHn, desHn, desURL, type, blocked });
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var contentScriptLocalStorageHandler = function(tabId, originURL) {
|
||||
var tabContext = µm.tabContextManager.lookup(tabId);
|
||||
let tabContext = µm.tabContextManager.lookup(tabId);
|
||||
if ( tabContext === null ) { return; }
|
||||
|
||||
var blocked = µm.mustBlock(
|
||||
tabContext.rootHostname,
|
||||
µm.URI.hostnameFromURI(originURL),
|
||||
'cookie'
|
||||
);
|
||||
let srcHn = tabContext.rootHostname,
|
||||
desHn = µm.URI.hostnameFromURI(originURL),
|
||||
type = 'cookie',
|
||||
blocked = µm.mustBlock(srcHn, desHn, type);
|
||||
|
||||
var pageStore = µm.pageStoreFromTabId(tabId);
|
||||
let pageStore = µm.pageStoreFromTabId(tabId);
|
||||
if ( pageStore !== null ) {
|
||||
var requestURL = originURL + '/{localStorage}';
|
||||
pageStore.recordRequest('cookie', requestURL, blocked);
|
||||
µm.logger.writeOne(tabId, 'net', tabContext.rootHostname, requestURL, 'cookie', blocked);
|
||||
let desURL = originURL + '/{localStorage}';
|
||||
pageStore.recordRequest(type, desURL, blocked);
|
||||
µm.logger.writeOne({ tabId, srcHn, desHn, desURL, type, blocked });
|
||||
}
|
||||
|
||||
var removeStorage = blocked && µm.userSettings.deleteLocalStorage;
|
||||
|
@ -545,13 +576,13 @@ var onMessage = function(request, sender, callback) {
|
|||
break;
|
||||
}
|
||||
|
||||
var tabId = sender && sender.tab ? sender.tab.id || 0 : 0,
|
||||
let tabId = sender && sender.tab ? sender.tab.id || 0 : 0,
|
||||
tabContext = µm.tabContextManager.lookup(tabId),
|
||||
rootHostname = tabContext && tabContext.rootHostname,
|
||||
srcHn = tabContext && tabContext.rootHostname,
|
||||
pageStore = µm.pageStoreFromTabId(tabId);
|
||||
|
||||
// Sync
|
||||
var response;
|
||||
let response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'contentScriptHasLocalStorage':
|
||||
|
@ -565,8 +596,8 @@ var onMessage = function(request, sender, callback) {
|
|||
case 'mustRenderNoscriptTags?':
|
||||
if ( tabContext === null ) { break; }
|
||||
response =
|
||||
µm.tMatrix.mustBlock(rootHostname, rootHostname, 'script') &&
|
||||
µm.tMatrix.evaluateSwitchZ('noscript-spoof', rootHostname);
|
||||
µm.tMatrix.mustBlock(srcHn, srcHn, 'script') &&
|
||||
µm.tMatrix.evaluateSwitchZ('noscript-spoof', srcHn);
|
||||
if ( pageStore !== null ) {
|
||||
pageStore.hasNoscriptTags = true;
|
||||
}
|
||||
|
@ -578,15 +609,25 @@ var onMessage = function(request, sender, callback) {
|
|||
|
||||
case 'securityPolicyViolation':
|
||||
if ( request.directive === 'worker-src' ) {
|
||||
var url = µm.URI.hostnameFromURI(request.blockedURI) !== '' ?
|
||||
request.blockedURI :
|
||||
request.documentURI;
|
||||
let desURL = request.blockedURI;
|
||||
let desHn = µm.URI.hostnameFromURI(desURL);
|
||||
if ( desHn === '' ) {
|
||||
desURL = request.documentURI;
|
||||
desHn = µm.URI.hostnameFromURI(desURL);
|
||||
}
|
||||
if ( pageStore !== null ) {
|
||||
pageStore.hasWebWorkers = true;
|
||||
pageStore.recordRequest('script', url, request.blocked);
|
||||
pageStore.recordRequest('script', desURL, request.blocked);
|
||||
}
|
||||
if ( tabContext !== null ) {
|
||||
µm.logger.writeOne(tabId, 'net', rootHostname, url, 'worker', request.blocked);
|
||||
µm.logger.writeOne({
|
||||
tabId,
|
||||
srcHn,
|
||||
desHn,
|
||||
desURL,
|
||||
type: 'worker',
|
||||
blocked: request.blocked
|
||||
});
|
||||
}
|
||||
} else if ( request.directive === 'script-src' ) {
|
||||
foundInlineCode(tabId, pageStore, request, 'script');
|
||||
|
@ -597,7 +638,7 @@ var onMessage = function(request, sender, callback) {
|
|||
|
||||
case 'shutdown?':
|
||||
if ( tabContext !== null ) {
|
||||
response = µm.tMatrix.evaluateSwitchZ('matrix-off', rootHostname);
|
||||
response = µm.tMatrix.evaluateSwitchZ('matrix-off', srcHn);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -936,6 +977,17 @@ var onMessage = function(request, sender, callback) {
|
|||
var response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'getPublicSuffixListData':
|
||||
response = publicSuffixList.toSelfie();
|
||||
break;
|
||||
|
||||
case 'getRuleEditorOptions':
|
||||
response = {
|
||||
colorBlindFriendly: µm.userSettings.colorBlindFriendly,
|
||||
popupScopeLevel: µm.userSettings.popupScopeLevel
|
||||
};
|
||||
break;
|
||||
|
||||
case 'readMany':
|
||||
if (
|
||||
µm.logger.ownerId !== undefined &&
|
||||
|
|
107
src/js/popup.js
107
src/js/popup.js
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a browser extension to black/white list 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
|
||||
|
@ -19,7 +19,7 @@
|
|||
Home: https://github.com/gorhill/uMatrix
|
||||
*/
|
||||
|
||||
/* global punycode, uDom */
|
||||
/* global punycode, uDom, uMatrixScopeWidget */
|
||||
/* jshint esnext: true, bitwise: false */
|
||||
|
||||
'use strict';
|
||||
|
@ -501,22 +501,20 @@ function getCellAction(hostname, type, leaning) {
|
|||
|
||||
function handleFilter(button, leaning) {
|
||||
// our parent cell knows who we are
|
||||
var cell = button.ancestors('div.matCell'),
|
||||
let cell = button.ancestors('div.matCell'),
|
||||
expandos = expandosFromNode(cell),
|
||||
type = expandos.reqType,
|
||||
desHostname = expandos.hostname;
|
||||
// https://github.com/gorhill/uMatrix/issues/24
|
||||
// No hostname can happen -- like with blacklist meta row
|
||||
if ( desHostname === '' ) {
|
||||
return;
|
||||
}
|
||||
var request = {
|
||||
if ( desHostname === '' ) { return; }
|
||||
let request = {
|
||||
what: getCellAction(desHostname, type, leaning),
|
||||
srcHostname: matrixSnapshot.scope,
|
||||
desHostname: desHostname,
|
||||
type: type
|
||||
};
|
||||
vAPI.messaging.send('popup.js', request, updateMatrixSnapshot);
|
||||
vAPI.messaging.send('default', request, updateMatrixSnapshot);
|
||||
}
|
||||
|
||||
function handleWhitelistFilter(button) {
|
||||
|
@ -1055,7 +1053,11 @@ var makeMenu = function() {
|
|||
makeMatrixGroup4(groupStats[4]);
|
||||
endMatrixUpdate();
|
||||
|
||||
initScopeCell();
|
||||
uMatrixScopeWidget.init(
|
||||
matrixSnapshot.domain,
|
||||
matrixSnapshot.hostname,
|
||||
matrixSnapshot.scope
|
||||
);
|
||||
updateMatrixButtons();
|
||||
resizePopup();
|
||||
recipeManager.fetch();
|
||||
|
@ -1098,91 +1100,15 @@ function initMenuEnvironment() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
// Create page scopes for the web page
|
||||
|
||||
function selectGlobalScope() {
|
||||
if ( matrixSnapshot.scope === '*' ) { return; }
|
||||
matrixSnapshot.scope = '*';
|
||||
document.body.classList.add('globalScope');
|
||||
matrixSnapshot.tMatrixModifiedTime = undefined;
|
||||
updateMatrixSnapshot();
|
||||
dropDownMenuHide();
|
||||
}
|
||||
|
||||
function selectSpecificScope(ev) {
|
||||
var newScope = ev.target.getAttribute('data-scope');
|
||||
function scopeChangeHandler(ev) {
|
||||
let newScope = ev.detail.scope;
|
||||
if ( !newScope || matrixSnapshot.scope === newScope ) { return; }
|
||||
document.body.classList.remove('globalScope');
|
||||
matrixSnapshot.scope = newScope;
|
||||
matrixSnapshot.tMatrixModifiedTime = undefined;
|
||||
updateMatrixSnapshot();
|
||||
dropDownMenuHide();
|
||||
}
|
||||
|
||||
function initScopeCell() {
|
||||
// It's possible there is no page URL at this point: some pages cannot
|
||||
// be filtered by uMatrix.
|
||||
if ( matrixSnapshot.url === '' ) { return; }
|
||||
var specificScope = uDom.nodeFromId('specificScope');
|
||||
|
||||
while ( specificScope.firstChild !== null ) {
|
||||
specificScope.removeChild(specificScope.firstChild);
|
||||
}
|
||||
|
||||
// Fill in the scope menu entries
|
||||
var pos = matrixSnapshot.domain.indexOf('.');
|
||||
var tld, labels;
|
||||
if ( pos === -1 ) {
|
||||
tld = '';
|
||||
labels = matrixSnapshot.hostname;
|
||||
} else {
|
||||
tld = matrixSnapshot.domain.slice(pos + 1);
|
||||
labels = matrixSnapshot.hostname.slice(0, -tld.length);
|
||||
}
|
||||
var beg = 0, span, label;
|
||||
while ( beg < labels.length ) {
|
||||
pos = labels.indexOf('.', beg);
|
||||
if ( pos === -1 ) {
|
||||
pos = labels.length;
|
||||
} else {
|
||||
pos += 1;
|
||||
}
|
||||
label = document.createElement('span');
|
||||
label.appendChild(
|
||||
document.createTextNode(punycode.toUnicode(labels.slice(beg, pos)))
|
||||
);
|
||||
span = document.createElement('span');
|
||||
span.setAttribute('data-scope', labels.slice(beg) + tld);
|
||||
span.appendChild(label);
|
||||
specificScope.appendChild(span);
|
||||
beg = pos;
|
||||
}
|
||||
if ( tld !== '' ) {
|
||||
label = document.createElement('span');
|
||||
label.appendChild(document.createTextNode(punycode.toUnicode(tld)));
|
||||
span = document.createElement('span');
|
||||
span.setAttribute('data-scope', tld);
|
||||
span.appendChild(label);
|
||||
specificScope.appendChild(span);
|
||||
}
|
||||
updateScopeCell();
|
||||
}
|
||||
|
||||
function updateScopeCell() {
|
||||
var specificScope = uDom.nodeFromId('specificScope'),
|
||||
isGlobal = matrixSnapshot.scope === '*';
|
||||
document.body.classList.toggle('globalScope', isGlobal);
|
||||
specificScope.classList.toggle('on', !isGlobal);
|
||||
uDom.nodeFromId('globalScope').classList.toggle('on', isGlobal);
|
||||
for ( var node of specificScope.children ) {
|
||||
node.classList.toggle(
|
||||
'on',
|
||||
!isGlobal &&
|
||||
matrixSnapshot.scope.endsWith(node.getAttribute('data-scope'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
function updateMatrixSwitches() {
|
||||
|
@ -1277,7 +1203,7 @@ function revertMatrix() {
|
|||
// Buttons which are affected by any changes in the matrix
|
||||
|
||||
function updateMatrixButtons() {
|
||||
updateScopeCell();
|
||||
uMatrixScopeWidget.update(matrixSnapshot.scope);
|
||||
updateMatrixSwitches();
|
||||
updatePersistButton();
|
||||
}
|
||||
|
@ -1285,7 +1211,7 @@ function updateMatrixButtons() {
|
|||
/******************************************************************************/
|
||||
|
||||
function buttonReloadHandler(ev) {
|
||||
vAPI.messaging.send('popup.js', {
|
||||
vAPI.messaging.send('default', {
|
||||
what: 'forceReloadTab',
|
||||
tabId: matrixSnapshot.tabId,
|
||||
bypassCache: ev.ctrlKey || ev.metaKey || ev.shiftKey
|
||||
|
@ -1637,8 +1563,7 @@ matrixCellHotspots = uDom('#cellHotspots').detach();
|
|||
uDom('body')
|
||||
.on('mouseenter', '.matCell', mouseenterMatrixCellHandler)
|
||||
.on('mouseleave', '.matCell', mouseleaveMatrixCellHandler);
|
||||
uDom('#specificScope').on('click', selectSpecificScope);
|
||||
uDom('#globalScope').on('click', selectGlobalScope);
|
||||
window.addEventListener('uMatrixScopeWidgetChange', scopeChangeHandler);
|
||||
uDom('#buttonMtxSwitches').on('click', function(ev) {
|
||||
dropDownMenuShow(ev.target);
|
||||
});
|
||||
|
|
152
src/js/scope-selector.js
Normal file
152
src/js/scope-selector.js
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a browser extension to black/white list 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/uMatrix
|
||||
*/
|
||||
|
||||
/* exported uMatrixScopeWidget */
|
||||
/* global punycode */
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
let uMatrixScopeWidget = (function() {
|
||||
|
||||
// Start of private namespace
|
||||
// >>>>>>>>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
let currentScope = '';
|
||||
let listening = false;
|
||||
|
||||
let fireChangeEvent = function() {
|
||||
document.body.setAttribute('data-scope', currentScope);
|
||||
let ev = new CustomEvent(
|
||||
'uMatrixScopeWidgetChange',
|
||||
{
|
||||
detail: { scope: currentScope }
|
||||
}
|
||||
);
|
||||
window.dispatchEvent(ev);
|
||||
};
|
||||
|
||||
let init = function(domain, hostname, scope, container) {
|
||||
if ( typeof domain !== 'string' || domain === '' ) { return; }
|
||||
|
||||
currentScope = '';
|
||||
|
||||
// Reset widget
|
||||
if ( !container ) {
|
||||
container = document;
|
||||
}
|
||||
let specificScope = container.querySelector('#specificScope');
|
||||
while ( specificScope.firstChild !== null ) {
|
||||
specificScope.removeChild(specificScope.firstChild);
|
||||
}
|
||||
|
||||
// Fill in the scope menu entries
|
||||
let pos = domain.indexOf('.');
|
||||
let tld, labels;
|
||||
if ( pos === -1 ) {
|
||||
tld = '';
|
||||
labels = hostname;
|
||||
} else {
|
||||
tld = domain.slice(pos + 1);
|
||||
labels = hostname.slice(0, -tld.length);
|
||||
}
|
||||
let beg = 0;
|
||||
while ( beg < labels.length ) {
|
||||
pos = labels.indexOf('.', beg);
|
||||
if ( pos === -1 ) {
|
||||
pos = labels.length;
|
||||
} else {
|
||||
pos += 1;
|
||||
}
|
||||
let label = document.createElement('span');
|
||||
label.appendChild(
|
||||
document.createTextNode(punycode.toUnicode(labels.slice(beg, pos)))
|
||||
);
|
||||
let span = document.createElement('span');
|
||||
span.setAttribute('data-scope', labels.slice(beg) + tld);
|
||||
span.appendChild(label);
|
||||
specificScope.appendChild(span);
|
||||
beg = pos;
|
||||
}
|
||||
if ( tld !== '' ) {
|
||||
let label = document.createElement('span');
|
||||
label.appendChild(document.createTextNode(punycode.toUnicode(tld)));
|
||||
let span = document.createElement('span');
|
||||
span.setAttribute('data-scope', tld);
|
||||
span.appendChild(label);
|
||||
specificScope.appendChild(span);
|
||||
}
|
||||
|
||||
if ( listening === false ) {
|
||||
container.querySelector('#specificScope').addEventListener(
|
||||
'click',
|
||||
ev => { update(ev.target.getAttribute('data-scope')); }
|
||||
);
|
||||
container.querySelector('#globalScope').addEventListener(
|
||||
'click',
|
||||
( ) => { update('*'); }
|
||||
);
|
||||
listening = true;
|
||||
}
|
||||
|
||||
update(scope, container);
|
||||
};
|
||||
|
||||
let getScope = function() {
|
||||
return currentScope;
|
||||
};
|
||||
|
||||
let update = function(scope, container) {
|
||||
if ( scope === currentScope ) { return; }
|
||||
currentScope = scope;
|
||||
if ( !container ) {
|
||||
container = document;
|
||||
}
|
||||
let specificScope = container.querySelector('#specificScope'),
|
||||
isGlobal = scope === '*';
|
||||
specificScope.classList.toggle('on', !isGlobal);
|
||||
container.querySelector('#globalScope').classList.toggle('on', isGlobal);
|
||||
for ( let node of specificScope.children ) {
|
||||
node.classList.toggle(
|
||||
'on',
|
||||
!isGlobal &&
|
||||
scope.endsWith(node.getAttribute('data-scope'))
|
||||
);
|
||||
}
|
||||
fireChangeEvent();
|
||||
};
|
||||
|
||||
return { init, getScope, update };
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// <<<<<<<<
|
||||
// End of private namespace
|
||||
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
|
@ -32,29 +32,29 @@
|
|||
// Intercept and filter web requests according to white and black lists.
|
||||
|
||||
var onBeforeRootFrameRequestHandler = function(details) {
|
||||
var µm = µMatrix;
|
||||
var requestURL = details.url;
|
||||
var requestHostname = µm.URI.hostnameFromURI(requestURL);
|
||||
var tabId = details.tabId;
|
||||
let µm = µMatrix;
|
||||
let desURL = details.url;
|
||||
let desHn = µm.URI.hostnameFromURI(desURL);
|
||||
let tabId = details.tabId;
|
||||
|
||||
µm.tabContextManager.push(tabId, requestURL);
|
||||
µm.tabContextManager.push(tabId, desURL);
|
||||
|
||||
var tabContext = µm.tabContextManager.mustLookup(tabId);
|
||||
var rootHostname = tabContext.rootHostname;
|
||||
let tabContext = µm.tabContextManager.mustLookup(tabId);
|
||||
let srcHn = tabContext.rootHostname;
|
||||
|
||||
// Disallow request as per matrix?
|
||||
var block = µm.mustBlock(rootHostname, requestHostname, 'doc');
|
||||
let blocked = µm.mustBlock(srcHn, desHn, 'doc');
|
||||
|
||||
var pageStore = µm.pageStoreFromTabId(tabId);
|
||||
pageStore.recordRequest('doc', requestURL, block);
|
||||
let pageStore = µm.pageStoreFromTabId(tabId);
|
||||
pageStore.recordRequest('doc', desURL, blocked);
|
||||
pageStore.perLoadAllowedRequestCount = 0;
|
||||
pageStore.perLoadBlockedRequestCount = 0;
|
||||
µm.logger.writeOne(tabId, 'net', rootHostname, requestURL, 'doc', block);
|
||||
µm.logger.writeOne({ tabId, srcHn, desHn, desURL, type: 'doc', blocked });
|
||||
|
||||
// Not blocked
|
||||
if ( !block ) {
|
||||
let redirectURL = maybeRedirectRootFrame(requestHostname, requestURL);
|
||||
if ( redirectURL !== requestURL ) {
|
||||
if ( !blocked ) {
|
||||
let redirectURL = maybeRedirectRootFrame(desHn, desURL);
|
||||
if ( redirectURL !== desURL ) {
|
||||
return { redirectUrl: redirectURL };
|
||||
}
|
||||
µm.cookieHunter.recordPageCookies(pageStore);
|
||||
|
@ -62,11 +62,7 @@ var onBeforeRootFrameRequestHandler = function(details) {
|
|||
}
|
||||
|
||||
// Blocked
|
||||
var query = btoa(JSON.stringify({
|
||||
url: requestURL,
|
||||
hn: requestHostname,
|
||||
why: '?'
|
||||
}));
|
||||
let query = btoa(JSON.stringify({ url: desURL, hn: desHn, why: '?' }));
|
||||
|
||||
vAPI.tabs.replace(tabId, vAPI.getURL('main-blocked.html?details=') + query);
|
||||
|
||||
|
@ -99,19 +95,19 @@ var maybeRedirectRootFrame = function(hostname, url) {
|
|||
// Intercept and filter web requests according to white and black lists.
|
||||
|
||||
var onBeforeRequestHandler = function(details) {
|
||||
var µm = µMatrix,
|
||||
let µm = µMatrix,
|
||||
µmuri = µm.URI,
|
||||
requestURL = details.url,
|
||||
requestScheme = µmuri.schemeFromURI(requestURL);
|
||||
desURL = details.url,
|
||||
desScheme = µmuri.schemeFromURI(desURL);
|
||||
|
||||
if ( µmuri.isNetworkScheme(requestScheme) === false ) { return; }
|
||||
if ( µmuri.isNetworkScheme(desScheme) === false ) { return; }
|
||||
|
||||
var requestType = requestTypeNormalizer[details.type] || 'other';
|
||||
let type = requestTypeNormalizer[details.type] || 'other';
|
||||
|
||||
// https://github.com/gorhill/httpswitchboard/issues/303
|
||||
// Wherever the main doc comes from, create a receiver page URL: synthetize
|
||||
// one if needed.
|
||||
if ( requestType === 'doc' && details.parentFrameId === -1 ) {
|
||||
if ( type === 'doc' && details.parentFrameId === -1 ) {
|
||||
return onBeforeRootFrameRequestHandler(details);
|
||||
}
|
||||
|
||||
|
@ -122,9 +118,9 @@ var onBeforeRequestHandler = function(details) {
|
|||
// to scope on unknown scheme? Etc.
|
||||
// https://github.com/gorhill/httpswitchboard/issues/191
|
||||
// https://github.com/gorhill/httpswitchboard/issues/91#issuecomment-37180275
|
||||
var tabContext = µm.tabContextManager.mustLookup(details.tabId),
|
||||
let tabContext = µm.tabContextManager.mustLookup(details.tabId),
|
||||
tabId = tabContext.tabId,
|
||||
rootHostname = tabContext.rootHostname,
|
||||
srcHn = tabContext.rootHostname,
|
||||
specificity = 0;
|
||||
|
||||
// https://github.com/gorhill/uMatrix/issues/995
|
||||
|
@ -137,18 +133,16 @@ var onBeforeRequestHandler = function(details) {
|
|||
µmuri.isNetworkURI(details.documentUrl)
|
||||
) {
|
||||
tabId = µm.tabContextManager.tabIdFromURL(details.documentUrl);
|
||||
rootHostname = µmuri.hostnameFromURI(
|
||||
srcHn = µmuri.hostnameFromURI(
|
||||
µm.normalizePageURL(0, details.documentUrl)
|
||||
);
|
||||
}
|
||||
|
||||
// Filter through matrix
|
||||
var block = µm.tMatrix.mustBlock(
|
||||
rootHostname,
|
||||
µmuri.hostnameFromURI(requestURL),
|
||||
requestType
|
||||
);
|
||||
if ( block ) {
|
||||
let desHn = µmuri.hostnameFromURI(desURL);
|
||||
|
||||
let blocked = µm.tMatrix.mustBlock(srcHn, desHn, type);
|
||||
if ( blocked ) {
|
||||
specificity = µm.tMatrix.specificityRegister;
|
||||
}
|
||||
|
||||
|
@ -158,21 +152,23 @@ var onBeforeRequestHandler = function(details) {
|
|||
// processing has already been performed, and that a synthetic URL has
|
||||
// been constructed for logging purpose. Use this synthetic URL if
|
||||
// it is available.
|
||||
var pageStore = µm.mustPageStoreFromTabId(tabId);
|
||||
let pageStore = µm.mustPageStoreFromTabId(tabId);
|
||||
|
||||
// Enforce strict secure connection?
|
||||
if ( tabContext.secure && µmuri.isSecureScheme(requestScheme) === false ) {
|
||||
if ( tabContext.secure && µmuri.isSecureScheme(desScheme) === false ) {
|
||||
pageStore.hasMixedContent = true;
|
||||
if ( block === false ) {
|
||||
block = µm.tMatrix.evaluateSwitchZ('https-strict', rootHostname);
|
||||
if ( blocked === false ) {
|
||||
blocked = µm.tMatrix.evaluateSwitchZ('https-strict', srcHn);
|
||||
}
|
||||
}
|
||||
|
||||
pageStore.recordRequest(requestType, requestURL, block);
|
||||
µm.logger.writeOne(tabId, 'net', rootHostname, requestURL, details.type, block);
|
||||
pageStore.recordRequest(type, desURL, blocked);
|
||||
if ( µm.logger.enabled ) {
|
||||
µm.logger.writeOne({ tabId, srcHn, desHn, desURL, type, blocked });
|
||||
}
|
||||
|
||||
if ( block ) {
|
||||
pageStore.cacheBlockedCollapsible(requestType, requestURL, specificity);
|
||||
if ( blocked ) {
|
||||
pageStore.cacheBlockedCollapsible(type, desURL, specificity);
|
||||
return { 'cancel': true };
|
||||
}
|
||||
};
|
||||
|
@ -184,11 +180,11 @@ var onBeforeRequestHandler = function(details) {
|
|||
var onBeforeSendHeadersHandler = function(details) {
|
||||
let µm = µMatrix,
|
||||
µmuri = µm.URI,
|
||||
requestURL = details.url,
|
||||
requestScheme = µmuri.schemeFromURI(requestURL);
|
||||
desURL = details.url,
|
||||
desScheme = µmuri.schemeFromURI(desURL);
|
||||
|
||||
// Ignore non-network schemes
|
||||
if ( µmuri.isNetworkScheme(requestScheme) === false ) { return; }
|
||||
if ( µmuri.isNetworkScheme(desScheme) === false ) { return; }
|
||||
|
||||
// Re-classify orphan HTTP requests as behind-the-scene requests. There is
|
||||
// not much else which can be done, because there are URLs
|
||||
|
@ -227,10 +223,10 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
if ( headerIndex !== -1 ) {
|
||||
let headerValue = requestHeaders[headerIndex].value;
|
||||
if ( headerValue !== '' ) {
|
||||
var block = µm.userSettings.processHyperlinkAuditing;
|
||||
pageStore.recordRequest('other', requestURL + '{Ping-To:' + headerValue + '}', block);
|
||||
µm.logger.writeOne(tabId, 'net', '', requestURL, 'ping', block);
|
||||
if ( block ) {
|
||||
let blocked = µm.userSettings.processHyperlinkAuditing;
|
||||
pageStore.recordRequest('other', desURL + '{Ping-To:' + headerValue + '}', blocked);
|
||||
µm.logger.writeOne({ tabId, desURL, type: 'ping', blocked });
|
||||
if ( blocked ) {
|
||||
µm.hyperlinkAuditingFoiledCounter += 1;
|
||||
return { 'cancel': true };
|
||||
}
|
||||
|
@ -240,8 +236,8 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
// If we reach this point, request is not blocked, so what is left to do
|
||||
// is to sanitize headers.
|
||||
|
||||
let rootHostname = pageStore.pageHostname,
|
||||
requestHostname = µmuri.hostnameFromURI(requestURL),
|
||||
let srcHn = pageStore.pageHostname,
|
||||
desHn = µmuri.hostnameFromURI(desURL),
|
||||
modified = false;
|
||||
|
||||
// Process `Cookie` header.
|
||||
|
@ -249,7 +245,7 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
headerIndex = headerIndexFromName('cookie', requestHeaders);
|
||||
if (
|
||||
headerIndex !== -1 &&
|
||||
µm.mustBlock(rootHostname, requestHostname, 'cookie')
|
||||
µm.mustBlock(srcHn, desHn, 'cookie')
|
||||
) {
|
||||
modified = true;
|
||||
let headerValue = requestHeaders[headerIndex].value;
|
||||
|
@ -257,7 +253,12 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
µm.cookieHeaderFoiledCounter++;
|
||||
if ( requestType === 'doc' ) {
|
||||
pageStore.perLoadBlockedRequestCount++;
|
||||
µm.logger.writeOne(tabId, 'net', '', headerValue, 'COOKIE', true);
|
||||
µm.logger.writeOne({
|
||||
tabId,
|
||||
srcHn,
|
||||
header: { name: 'COOKIE', value: headerValue },
|
||||
change: -1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,23 +286,33 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
if ( headerIndex !== -1 ) {
|
||||
let headerValue = requestHeaders[headerIndex].value;
|
||||
if ( headerValue !== '' ) {
|
||||
let toDomain = µmuri.domainFromHostname(requestHostname);
|
||||
let toDomain = µmuri.domainFromHostname(desHn);
|
||||
if ( toDomain !== '' && toDomain !== µmuri.domainFromURI(headerValue) ) {
|
||||
pageStore.has3pReferrer = true;
|
||||
if ( µm.tMatrix.evaluateSwitchZ('referrer-spoof', rootHostname) ) {
|
||||
if ( µm.tMatrix.evaluateSwitchZ('referrer-spoof', srcHn) ) {
|
||||
modified = true;
|
||||
let newValue;
|
||||
if ( details.method === 'GET' ) {
|
||||
newValue = requestHeaders[headerIndex].value =
|
||||
requestScheme + '://' + requestHostname + '/';
|
||||
desScheme + '://' + desHn + '/';
|
||||
} else {
|
||||
requestHeaders.splice(headerIndex, 1);
|
||||
}
|
||||
if ( pageStore.perLoadBlockedReferrerCount === 0 ) {
|
||||
pageStore.perLoadBlockedRequestCount += 1;
|
||||
µm.logger.writeOne(tabId, 'net', '', headerValue, 'REFERER', true);
|
||||
µm.logger.writeOne({
|
||||
tabId,
|
||||
srcHn,
|
||||
header: { name: 'REFERER', value: headerValue },
|
||||
change: -1
|
||||
});
|
||||
if ( newValue !== undefined ) {
|
||||
µm.logger.writeOne(tabId, 'net', '', newValue, 'REFERER', false);
|
||||
µm.logger.writeOne({
|
||||
tabId,
|
||||
srcHn,
|
||||
header: { name: 'REFERER', value: newValue },
|
||||
change: +1
|
||||
});
|
||||
}
|
||||
}
|
||||
pageStore.perLoadBlockedReferrerCount += 1;
|
||||
|
@ -329,7 +340,7 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
|
||||
var onHeadersReceived = function(details) {
|
||||
// Ignore schemes other than 'http...'
|
||||
var µm = µMatrix,
|
||||
let µm = µMatrix,
|
||||
tabId = details.tabId,
|
||||
requestURL = details.url,
|
||||
requestType = requestTypeNormalizer[details.type] || 'other';
|
||||
|
@ -340,25 +351,25 @@ var onHeadersReceived = function(details) {
|
|||
µm.tabContextManager.push(tabId, requestURL);
|
||||
}
|
||||
|
||||
var tabContext = µm.tabContextManager.lookup(tabId);
|
||||
let tabContext = µm.tabContextManager.lookup(tabId);
|
||||
if ( tabContext === null ) { return; }
|
||||
|
||||
var csp = [],
|
||||
let csp = [],
|
||||
cspReport = [],
|
||||
rootHostname = tabContext.rootHostname,
|
||||
requestHostname = µm.URI.hostnameFromURI(requestURL);
|
||||
srcHn = tabContext.rootHostname,
|
||||
desHn = µm.URI.hostnameFromURI(requestURL);
|
||||
|
||||
// Inline script tags.
|
||||
if ( µm.mustAllow(rootHostname, requestHostname, 'script' ) !== true ) {
|
||||
if ( µm.mustBlock(srcHn, desHn, 'script' ) ) {
|
||||
csp.push(µm.cspNoInlineScript);
|
||||
}
|
||||
|
||||
// Inline style tags.
|
||||
if ( µm.mustAllow(rootHostname, requestHostname, 'css' ) !== true ) {
|
||||
if ( µm.mustBlock(srcHn, desHn, 'css' ) ) {
|
||||
csp.push(µm.cspNoInlineStyle);
|
||||
}
|
||||
|
||||
if ( µm.tMatrix.evaluateSwitchZ('no-workers', rootHostname) ) {
|
||||
if ( µm.tMatrix.evaluateSwitchZ('no-workers', srcHn) ) {
|
||||
csp.push(µm.cspNoWorker);
|
||||
} else if ( µm.rawSettings.disableCSPReportInjection === false ) {
|
||||
cspReport.push(µm.cspNoWorker);
|
||||
|
@ -391,7 +402,12 @@ var onHeadersReceived = function(details) {
|
|||
value: cspTotal
|
||||
});
|
||||
if ( requestType === 'doc' ) {
|
||||
µm.logger.writeOne(tabId, 'net', '', cspRight, 'CSP', false);
|
||||
µm.logger.writeOne({
|
||||
tabId,
|
||||
srcHn,
|
||||
header: { name: 'CSP', value: cspRight },
|
||||
change: +1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="css/common.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/scope-selector.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/logger-ui.css">
|
||||
<link rel="shortcut icon" type="image/png" href="img/icon_16.png">
|
||||
<title data-i18n="loggerPageName"></title>
|
||||
|
@ -36,19 +37,45 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<div id="popupContainer">
|
||||
<div><span></span> <span></span></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style="display: none;">
|
||||
<div id="emphasizeTemplate"><span><span></span><b></b><span></span></span></div>
|
||||
<div id="hiddenTemplate"><span style="display:none;"></span></div>
|
||||
<div id="ruleEditor" class="modalDialog">
|
||||
<div class="dialog">
|
||||
<section class="scopeWidget">
|
||||
<span class="scope" id="specificScope"><span> </span></span><!--
|
||||
--><span class="scope" id="globalScope" data-scope="*" data-i18n-tip="matrixGlobalScopeTip"><span><span>∗</span></span></span>
|
||||
<div class="ruleEditorToolbar">
|
||||
<button type="button" class="buttonReload fa tip-anchor-right" data-i18n-tip="matrixReloadButton"></button>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<div class="ruleWidgets"></div>
|
||||
<div class="ruleEditorToolbar">
|
||||
<button type="button" class="buttonRevertScope fa scopeRel tip-anchor-right" tabindex="-1" data-i18n-tip="matrixRevertButtonTip"></button>
|
||||
<button type="button" class="buttonPersist fa scopeRel tip-anchor-right" data-i18n-tip="matrixPersistButtonTip"><span class="badge"></span></button>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ruleRowTemplate" style="display: none;">
|
||||
<div class="ruleRow"><!--
|
||||
--><span class="ruleCell" data-type="*"> </span><!--
|
||||
--><span class="ruleCell" data-type> </span><!--
|
||||
--></div>
|
||||
</div>
|
||||
<div id="ruleActionPicker"><div class="allowRule"></div><div class="blockRule"></div></div>
|
||||
</div>
|
||||
|
||||
<script src="lib/punycode.js"></script>
|
||||
<script src="lib/publicsuffixlist.js"></script>
|
||||
<script src="js/vapi-common.js"></script>
|
||||
<script src="js/vapi-client.js"></script>
|
||||
<script src="js/udom.js"></script>
|
||||
<script src="js/i18n.js"></script>
|
||||
<script src="js/scope-selector.js"></script>
|
||||
<script src="js/logger-ui.js"></script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css">
|
||||
<link rel="stylesheet" href="css/scope-selector.css" type="text/css">
|
||||
<link rel="stylesheet" href="css/popup.css" type="text/css">
|
||||
<title>uMatrix panel</title>
|
||||
</head>
|
||||
|
@ -119,6 +120,7 @@
|
|||
<script src="js/vapi-client.js"></script>
|
||||
<script src="js/udom.js"></script>
|
||||
<script src="js/i18n.js"></script>
|
||||
<script src="js/scope-selector.js"></script>
|
||||
<script src="js/popup.js"></script>
|
||||
</body>
|
||||
|
||||
|
|
Loading…
Reference in a new issue