mirror of
https://github.com/gorhill/uMatrix.git
synced 2024-05-25 14:40:28 +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.
|
||||
Copyright (C) 2014-2018 Raymond Hill
|
||||
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
|
||||
|
@ -199,6 +199,30 @@ Matrix.prototype.reset = function() {
|
|||
this.rules = new Map();
|
||||
this.rootValue = Matrix.RedIndirect;
|
||||
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 ) {
|
||||
this.switches.set(entry[0], entry[1]);
|
||||
}
|
||||
this.modifiedTime = other.modifiedTime;
|
||||
this.modified();
|
||||
return this;
|
||||
};
|
||||
|
||||
|
@ -268,7 +292,7 @@ Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) {
|
|||
} else {
|
||||
this.switches.set(srcHostname, bits);
|
||||
}
|
||||
this.modifiedTime = Date.now();
|
||||
this.modified();
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -290,7 +314,7 @@ Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) {
|
|||
} else {
|
||||
this.rules.set(k, newBitmap);
|
||||
}
|
||||
this.modifiedTime = Date.now();
|
||||
this.modified();
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -531,7 +555,7 @@ Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) {
|
|||
} else {
|
||||
this.switches.set(srcHostname, bits);
|
||||
}
|
||||
this.modifiedTime = Date.now();
|
||||
this.modified();
|
||||
state = this.evaluateSwitchZ(switchName, srcHostname);
|
||||
if ( state === newState ) {
|
||||
return true;
|
||||
|
@ -645,7 +669,7 @@ Matrix.prototype.fromArray = function(lines, append) {
|
|||
if ( append !== true ) {
|
||||
this.assign(matrix);
|
||||
}
|
||||
this.modifiedTime = Date.now();
|
||||
this.modified();
|
||||
};
|
||||
|
||||
Matrix.prototype.toArray = function() {
|
||||
|
@ -707,7 +731,7 @@ Matrix.prototype.fromString = function(text, append) {
|
|||
this.assign(matrix);
|
||||
}
|
||||
|
||||
this.modifiedTime = Date.now();
|
||||
this.modified();
|
||||
};
|
||||
|
||||
Matrix.prototype.toString = function() {
|
||||
|
@ -750,7 +774,7 @@ Matrix.prototype.fromSelfie = function(selfie) {
|
|||
if ( selfie.version !== selfieVersion ) { return false; }
|
||||
this.switches = new Map(selfie.switches);
|
||||
this.rules = new Map(selfie.rules);
|
||||
this.modifiedTime = Date.now();
|
||||
this.modified();
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -229,6 +229,13 @@ var matrixSnapshot = function(pageStore, details) {
|
|||
let µmuri = µm.URI;
|
||||
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 ) {
|
||||
let pos = entry[0].indexOf(' ');
|
||||
let reqHostname = entry[0].slice(0, pos);
|
||||
|
|
|
@ -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
|
||||
|
@ -483,6 +483,97 @@ vAPI.net.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() {
|
||||
|
|
Loading…
Reference in a new issue