mirror of
https://github.com/gorhill/uMatrix.git
synced 2024-06-17 09:44:59 +12:00
fix #589: use DOM-based CSP directive (idea from 6e80d3f130
)
This commit is contained in:
parent
7f3122c5fd
commit
f075f96c58
62
src/js/contentscript-no-inline-script.js
Normal file
62
src/js/contentscript-no-inline-script.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
uMatrix - a Chromium browser extension to black/white list requests.
|
||||||
|
Copyright (C) 2018 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// The idea of using <meta http-equiv> to enforce CSP directive has been
|
||||||
|
// borrowed from NoScript:
|
||||||
|
// https://github.com/hackademix/noscript/commit/6e80d3f130773fc9a9123c5c4c2e97d63e90fa2a
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
let html = document.documentElement;
|
||||||
|
if ( html instanceof HTMLElement === false ) { return; }
|
||||||
|
|
||||||
|
let meta;
|
||||||
|
try {
|
||||||
|
meta = document.createElement('meta');
|
||||||
|
} catch(ex) {
|
||||||
|
}
|
||||||
|
if ( meta === undefined ) { return; }
|
||||||
|
meta.setAttribute('http-equiv', 'content-security-policy');
|
||||||
|
meta.setAttribute('content', "script-src 'unsafe-eval' blob: *");
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-security-policy
|
||||||
|
//
|
||||||
|
// Only a head element can be parent:
|
||||||
|
// > If the meta element is not a child of a head element, return.
|
||||||
|
//
|
||||||
|
// The CSP directive is enforced as soon as the meta tag is inserted:
|
||||||
|
// > Enforce the policy policy.
|
||||||
|
let head = document.head,
|
||||||
|
parent = head;
|
||||||
|
if ( parent === null ) {
|
||||||
|
parent = document.createElement('head');
|
||||||
|
html.appendChild(parent);
|
||||||
|
}
|
||||||
|
parent.appendChild(meta);
|
||||||
|
|
||||||
|
// Restore DOM to its original state.
|
||||||
|
if ( head === null ) {
|
||||||
|
html.removeChild(parent);
|
||||||
|
} else {
|
||||||
|
parent.removeChild(meta);
|
||||||
|
}
|
||||||
|
})();
|
62
src/js/contentscript-no-workers.js
Normal file
62
src/js/contentscript-no-workers.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
uMatrix - a Chromium browser extension to black/white list requests.
|
||||||
|
Copyright (C) 2018 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// The idea of using <meta http-equiv> to enforce CSP directive has been
|
||||||
|
// borrowed from NoScript:
|
||||||
|
// https://github.com/hackademix/noscript/commit/6e80d3f130773fc9a9123c5c4c2e97d63e90fa2a
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
let html = document.documentElement;
|
||||||
|
if ( html instanceof HTMLElement === false ) { return; }
|
||||||
|
|
||||||
|
let meta;
|
||||||
|
try {
|
||||||
|
meta = document.createElement('meta');
|
||||||
|
} catch(ex) {
|
||||||
|
}
|
||||||
|
if ( meta === undefined ) { return; }
|
||||||
|
meta.setAttribute('http-equiv', 'content-security-policy');
|
||||||
|
meta.setAttribute('content', "worker-src 'none'");
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-security-policy
|
||||||
|
//
|
||||||
|
// Only a head element can be parent:
|
||||||
|
// > If the meta element is not a child of a head element, return.
|
||||||
|
//
|
||||||
|
// The CSP directive is enforced as soon as the meta tag is inserted:
|
||||||
|
// > Enforce the policy policy.
|
||||||
|
let head = document.head,
|
||||||
|
parent = head;
|
||||||
|
if ( parent === null ) {
|
||||||
|
parent = document.createElement('head');
|
||||||
|
html.appendChild(parent);
|
||||||
|
}
|
||||||
|
parent.appendChild(meta);
|
||||||
|
|
||||||
|
// Restore DOM to its original state.
|
||||||
|
if ( head === null ) {
|
||||||
|
html.removeChild(parent);
|
||||||
|
} else {
|
||||||
|
parent.removeChild(meta);
|
||||||
|
}
|
||||||
|
})();
|
|
@ -1,7 +1,7 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
uMatrix - a Chromium browser extension to black/white list requests.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -199,6 +199,30 @@ Matrix.prototype.reset = function() {
|
||||||
this.rules = new Map();
|
this.rules = new Map();
|
||||||
this.rootValue = Matrix.RedIndirect;
|
this.rootValue = Matrix.RedIndirect;
|
||||||
this.modifiedTime = 0;
|
this.modifiedTime = 0;
|
||||||
|
if ( this.modifyEventTimer !== undefined ) {
|
||||||
|
clearTimeout(this.modifyEventTimer);
|
||||||
|
}
|
||||||
|
this.modifyEventTimer = undefined;
|
||||||
|
this.modified();
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.modified = function() {
|
||||||
|
this.modifiedTime = Date.now();
|
||||||
|
if ( this.modifyEventTimer !== undefined ) { return; }
|
||||||
|
this.modifyEventTimer = vAPI.setTimeout(
|
||||||
|
( ) => {
|
||||||
|
this.modifyEventTimer = undefined;
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent(
|
||||||
|
'matrixRulesetChange',
|
||||||
|
{ detail: this }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
149
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -242,7 +266,7 @@ Matrix.prototype.assign = function(other) {
|
||||||
for ( entry of other.switches ) {
|
for ( entry of other.switches ) {
|
||||||
this.switches.set(entry[0], entry[1]);
|
this.switches.set(entry[0], entry[1]);
|
||||||
}
|
}
|
||||||
this.modifiedTime = other.modifiedTime;
|
this.modified();
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -268,7 +292,7 @@ Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) {
|
||||||
} else {
|
} else {
|
||||||
this.switches.set(srcHostname, bits);
|
this.switches.set(srcHostname, bits);
|
||||||
}
|
}
|
||||||
this.modifiedTime = Date.now();
|
this.modified();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -290,7 +314,7 @@ Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) {
|
||||||
} else {
|
} else {
|
||||||
this.rules.set(k, newBitmap);
|
this.rules.set(k, newBitmap);
|
||||||
}
|
}
|
||||||
this.modifiedTime = Date.now();
|
this.modified();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -531,7 +555,7 @@ Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) {
|
||||||
} else {
|
} else {
|
||||||
this.switches.set(srcHostname, bits);
|
this.switches.set(srcHostname, bits);
|
||||||
}
|
}
|
||||||
this.modifiedTime = Date.now();
|
this.modified();
|
||||||
state = this.evaluateSwitchZ(switchName, srcHostname);
|
state = this.evaluateSwitchZ(switchName, srcHostname);
|
||||||
if ( state === newState ) {
|
if ( state === newState ) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -645,7 +669,7 @@ Matrix.prototype.fromArray = function(lines, append) {
|
||||||
if ( append !== true ) {
|
if ( append !== true ) {
|
||||||
this.assign(matrix);
|
this.assign(matrix);
|
||||||
}
|
}
|
||||||
this.modifiedTime = Date.now();
|
this.modified();
|
||||||
};
|
};
|
||||||
|
|
||||||
Matrix.prototype.toArray = function() {
|
Matrix.prototype.toArray = function() {
|
||||||
|
@ -707,7 +731,7 @@ Matrix.prototype.fromString = function(text, append) {
|
||||||
this.assign(matrix);
|
this.assign(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.modifiedTime = Date.now();
|
this.modified();
|
||||||
};
|
};
|
||||||
|
|
||||||
Matrix.prototype.toString = function() {
|
Matrix.prototype.toString = function() {
|
||||||
|
@ -750,7 +774,7 @@ Matrix.prototype.fromSelfie = function(selfie) {
|
||||||
if ( selfie.version !== selfieVersion ) { return false; }
|
if ( selfie.version !== selfieVersion ) { return false; }
|
||||||
this.switches = new Map(selfie.switches);
|
this.switches = new Map(selfie.switches);
|
||||||
this.rules = new Map(selfie.rules);
|
this.rules = new Map(selfie.rules);
|
||||||
this.modifiedTime = Date.now();
|
this.modified();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
uMatrix - a browser extension to black/white list requests.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -229,6 +229,13 @@ var matrixSnapshot = function(pageStore, details) {
|
||||||
let µmuri = µm.URI;
|
let µmuri = µm.URI;
|
||||||
let anyIndex = headerIndices.get('*');
|
let anyIndex = headerIndices.get('*');
|
||||||
|
|
||||||
|
// Ensure that the current scope is also reported in the matrix. This may
|
||||||
|
// not be the case for documents which are fetched without going through
|
||||||
|
// our webRequest listener (ex. `file:`).
|
||||||
|
if ( pageStore.hostnameTypeCells.has(r.hostname + ' doc') === false ) {
|
||||||
|
pageStore.hostnameTypeCells.set(r.hostname + ' doc', new Set([ 0 ]));
|
||||||
|
}
|
||||||
|
|
||||||
for ( let entry of pageStore.hostnameTypeCells ) {
|
for ( let entry of pageStore.hostnameTypeCells ) {
|
||||||
let pos = entry[0].indexOf(' ');
|
let pos = entry[0].indexOf(' ');
|
||||||
let reqHostname = entry[0].slice(0, pos);
|
let reqHostname = entry[0].slice(0, pos);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
uMatrix - a browser extension to black/white list requests.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -483,6 +483,97 @@ vAPI.net.onHeadersReceived = {
|
||||||
callback: onHeadersReceived
|
callback: onHeadersReceived
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Use a `http-equiv` `meta` tag to enforce CSP directives for documents
|
||||||
|
which protocol is `file:` (which do not cause our webRequest.onHeadersReceived
|
||||||
|
handler to be called).
|
||||||
|
|
||||||
|
Idea borrowed from NoScript:
|
||||||
|
https://github.com/hackademix/noscript/commit/6e80d3f130773fc9a9123c5c4c2e97d63e90fa2a
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
if (
|
||||||
|
typeof self.browser !== 'object' ||
|
||||||
|
typeof browser.contentScripts !== 'object'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let csRules = [
|
||||||
|
{
|
||||||
|
name: 'script',
|
||||||
|
file: '/js/contentscript-no-inline-script.js',
|
||||||
|
pending: undefined,
|
||||||
|
registered: undefined,
|
||||||
|
mustRegister: false
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let csSwitches = [
|
||||||
|
{
|
||||||
|
name: 'no-workers',
|
||||||
|
file: '/js/contentscript-no-workers.js',
|
||||||
|
pending: undefined,
|
||||||
|
registered: undefined,
|
||||||
|
mustRegister: false
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let register = function(entry) {
|
||||||
|
if ( entry.pending !== undefined ) { return; }
|
||||||
|
entry.pending = browser.contentScripts.register({
|
||||||
|
js: [ { file: entry.file } ],
|
||||||
|
matches: [ 'file:///*' ],
|
||||||
|
runAt: 'document_start'
|
||||||
|
}).then(
|
||||||
|
result => {
|
||||||
|
if ( entry.mustRegister ) {
|
||||||
|
entry.registered = result;
|
||||||
|
}
|
||||||
|
entry.pending = undefined;
|
||||||
|
},
|
||||||
|
( ) => {
|
||||||
|
entry.registered = undefined;
|
||||||
|
entry.pending = undefined;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let unregister = function(entry) {
|
||||||
|
if ( entry.registered === undefined ) { return; }
|
||||||
|
entry.registered.unregister();
|
||||||
|
entry.registered = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
let handler = function(ev) {
|
||||||
|
let matrix = ev && ev.detail;
|
||||||
|
if ( matrix !== µMatrix.tMatrix ) { return; }
|
||||||
|
for ( let cs of csRules ) {
|
||||||
|
cs.mustRegister = matrix.mustBlock('file-scheme', 'file-scheme', cs.name);
|
||||||
|
if ( cs.mustRegister === (cs.registered !== undefined) ) { continue; }
|
||||||
|
if ( cs.mustRegister ) {
|
||||||
|
register(cs);
|
||||||
|
} else {
|
||||||
|
unregister(cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ( let cs of csSwitches ) {
|
||||||
|
cs.mustRegister = matrix.evaluateSwitchZ(cs.name, 'file-scheme');
|
||||||
|
if ( cs.mustRegister === (cs.registered !== undefined) ) { continue; }
|
||||||
|
if ( cs.mustRegister ) {
|
||||||
|
register(cs);
|
||||||
|
} else {
|
||||||
|
unregister(cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('matrixRulesetChange', handler);
|
||||||
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var start = function() {
|
var start = function() {
|
||||||
|
|
Loading…
Reference in a new issue