Browse Source

new way of handling blocked documents

pull/2/head
gorhill 10 years ago
parent
commit
ddaa948cf4
  1. 16
      src/_locales/en/messages.json
  2. 0
      src/css/noop.css
  3. 2
      src/js/background.js
  4. 76
      src/js/main-blocked.js
  5. 10
      src/js/messaging.js
  6. 21
      src/js/tab.js
  7. 127
      src/js/traffic.js
  8. 72
      src/main-blocked.html

16
src/_locales/en/messages.json

@ -572,6 +572,22 @@
"description": "Message asking user to confirm reset" "description": "Message asking user to confirm reset"
}, },
"mainBlockedPrompt1": {
"message": "uMatrix has prevented the following page from loading:",
"description": "English: uMatrix has prevented the following page from loading:"
},
"mainBlockedPrompt2": {
"message": "Because of the following rule",
"description": "English: Because of the following rule"
},
"mainBlockedBack" : {
"message": "Go back",
"description": "English: Go back"
},
"mainBlockedClose" : {
"message": "Close",
"description": "English: Close"
},
"commandRevertAll" : { "commandRevertAll" : {
"message": "Remove all temporary changes", "message": "Remove all temporary changes",

0
src/css/noop.css

2
src/js/background.js

@ -123,8 +123,6 @@ return {
behindTheSceneScope: 'behind-the-scene', behindTheSceneScope: 'behind-the-scene',
// Commonly encountered strings // Commonly encountered strings
chromeExtensionURLPrefix: 'chrome-extension://',
noopCSSURL: vAPI.getURL('css/noop.css'),
fontCSSURL: vAPI.getURL('css/fonts/Roboto_Condensed/RobotoCondensed-Regular.ttf'), fontCSSURL: vAPI.getURL('css/fonts/Roboto_Condensed/RobotoCondensed-Regular.ttf'),
noopFunc: function(){}, noopFunc: function(){},

76
src/js/main-blocked.js

@ -0,0 +1,76 @@
/*******************************************************************************
µMatrix - a browser extension to block requests.
Copyright (C) 2015 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/uBlock
*/
/* global uDom */
/******************************************************************************/
(function() {
'use strict';
/******************************************************************************/
var details = {};
(function() {
var matches = /details=([^&]+)/.exec(window.location.search);
if ( matches === null ) {
return;
}
details = JSON.parse(atob(matches[1]));
})();
/******************************************************************************/
uDom('.what').text(details.url);
uDom('#why').text(details.why.slice(3));
if ( window.history.length > 1 ) {
uDom('#back').on('click', function() { window.history.back(); });
uDom('#bye').css('display', 'none');
} else {
uDom('#bye').on('click', function() { window.close(); });
uDom('#back').css('display', 'none');
}
/******************************************************************************/
// See if the target hostname is still blacklisted, and if not, navigate to it.
var messager = vAPI.messaging.channel('main-blocked.js');
messager.send({
what: 'mustBlock',
scope: details.hn,
hostname: details.hn,
type: 'doc'
}, function(response) {
if ( response === false ) {
window.location.replace(details.url);
}
});
/******************************************************************************/
})();
/******************************************************************************/

10
src/js/messaging.js

@ -71,6 +71,14 @@ function onMessage(request, sender, callback) {
µm.utils.gotoURL(request); µm.utils.gotoURL(request);
break; break;
case 'mustBlock':
response = µm.mustBlock(
request.scope,
request.hostname,
request.type
);
break;
case 'reloadHostsFiles': case 'reloadHostsFiles':
µm.reloadHostsFiles(); µm.reloadHostsFiles();
break; break;
@ -168,7 +176,7 @@ var matrixSnapshot = function(tabId, details) {
// Allow examination of behind-the-scene requests // Allow examination of behind-the-scene requests
if ( if (
tabContext.rawURL.lastIndexOf(vAPI.getURL(''), 0) === 0 ||
tabContext.rawURL.lastIndexOf(vAPI.getURL('dashboard.html'), 0) === 0 ||
tabContext.rawURL === µm.behindTheSceneURL tabContext.rawURL === µm.behindTheSceneURL
) { ) {
tabId = µm.behindTheSceneTabId; tabId = µm.behindTheSceneTabId;

21
src/js/tab.js

@ -49,6 +49,20 @@ var µm = µMatrix;
if ( vAPI.isBehindTheSceneTabId(tabId) ) { if ( vAPI.isBehindTheSceneTabId(tabId) ) {
return 'http://behind-the-scene/'; return 'http://behind-the-scene/';
} }
// If the URL is that of our "blocked page" document, return the URL of
// the blocked page.
if ( pageURL.lastIndexOf(vAPI.getURL('main-blocked.html'), 0) === 0 ) {
var matches = /main-blocked\.html\?details=([^&]+)/.exec(pageURL);
if ( matches && matches.length === 2 ) {
try {
var details = JSON.parse(atob(matches[1]));
pageURL = details.url;
} catch (e) {
}
}
}
var uri = this.URI.set(pageURL); var uri = this.URI.set(pageURL);
var scheme = uri.scheme; var scheme = uri.scheme;
if ( scheme === 'https' || scheme === 'http' ) { if ( scheme === 'https' || scheme === 'http' ) {
@ -453,13 +467,6 @@ vAPI.tabs.registerListeners();
return this.pageStores[tabId]; return this.pageStores[tabId];
} }
// https://github.com/gorhill/httpswitchboard/issues/303
// Don't rebind pages blocked by µMatrix.
var blockedRootFramePrefix = this.webRequest.blockedRootFramePrefix;
if ( tabContext.rawURL.lastIndexOf(blockedRootFramePrefix, 0) === 0 ) {
return null;
}
var normalURL = tabContext.normalURL; var normalURL = tabContext.normalURL;
var pageStore = this.pageStores[tabId] || null; var pageStore = this.pageStores[tabId] || null;

127
src/js/traffic.js

@ -33,65 +33,6 @@
// The `id='uMatrix'` is important, it allows µMatrix to detect whether a // The `id='uMatrix'` is important, it allows µMatrix to detect whether a
// specific data URI originates from itself. // specific data URI originates from itself.
var rootFrameReplacement = [
'<!DOCTYPE html><html id="uMatrix">',
'<head>',
'<meta charset="utf-8" />',
'<style>',
'@font-face {',
'font-family:httpsb;',
'font-style:normal;',
'font-weight:400;',
'src: local("httpsb"),url("', µMatrix.fontCSSURL, '") format("truetype");',
'}',
'body {',
'margin:0;',
'border:0;',
'padding:0;',
'font:15px httpsb,sans-serif;',
'width:100%;',
'height:100%;',
'background-color:transparent;',
'background-size:10px 10px;',
'background-image:',
'repeating-linear-gradient(',
'-45deg,',
'rgba(204,0,0,0.5),rgba(204,0,0,0.5) 24%,',
'transparent 26%,transparent 49%,',
'rgba(204,0,0,0.5) 51%,rgba(204,0,0,0.5) 74%,',
'transparent 76%,transparent',
');',
'text-align: center;',
'}',
'#p {',
'margin:8px;',
'padding:4px;',
'display:inline-block;',
'background-color:white;',
'}',
'#t {',
'margin:2px;',
'border:0;',
'padding:0 2px;',
'display:inline-block;',
'}',
'#t b {',
'padding:0 4px;',
'background-color:#eee;',
'font-weight:normal;',
'}',
'</style>',
'<link href="{{cssURL}}?url={{originalURL}}&hostname={{hostname}}&t={{now}}" rel="stylesheet" type="text/css">',
'<title>Blocked by &mu;Matrix</title>',
'</head>',
'<body>',
'<div id="p">',
'<div id="t"><b>{{hostname}}</b> blocked by &mu;Matrix</div>',
'</div>',
'</body>',
'</html>'
].join('');
var subFrameReplacement = [ var subFrameReplacement = [
'<!DOCTYPE html>', '<!DOCTYPE html>',
'<html>', '<html>',
@ -152,43 +93,6 @@ var subFrameReplacement = [
/******************************************************************************/ /******************************************************************************/
// If it is HTTP Switchboard's root frame replacement URL, verify that
// the page that was blacklisted is still blacklisted, and if not,
// redirect to the previously blacklisted page.
var onBeforeChromeExtensionRequestHandler = function(details) {
var requestURL = details.url;
// console.debug('onBeforeChromeExtensionRequestHandler()> "%s": %o', details.url, details);
// rhill 2013-12-10: Avoid regex whenever a faster indexOf() can be used:
// here we can use fast indexOf() as a first filter -- which is executed
// for every single request (so speed matters).
var matches = requestURL.match(/url=([^&]+)&hostname=([^&]+)/);
if ( !matches ) {
return;
}
var µm = µMatrix;
var pageURL = decodeURIComponent(matches[1]);
var pageHostname = decodeURIComponent(matches[2]);
// Blacklisted as per matrix?
if ( µm.mustBlock(µm.scopeFromURL(pageURL), pageHostname, 'doc') ) {
return;
}
µMatrix.asyncJobs.add(
'gotoURL-' + details.tabId,
{ tabId: details.tabId, url: pageURL },
µm.utils.gotoURL,
200,
false
);
};
/******************************************************************************/
// Intercept and filter web requests according to white and black lists. // Intercept and filter web requests according to white and black lists.
var onBeforeRootFrameRequestHandler = function(details) { var onBeforeRootFrameRequestHandler = function(details) {
@ -199,7 +103,7 @@ var onBeforeRootFrameRequestHandler = function(details) {
µm.tabContextManager.push(tabId, requestURL); µm.tabContextManager.push(tabId, requestURL);
var tabContext = µm.tabContextManager.mustLookup(tabId); var tabContext = µm.tabContextManager.mustLookup(tabId);
var pageStore = µm.bindTabToPageStats(tabId, 'weak');
var pageStore = µm.bindTabToPageStats(tabId);
// Disallow request as per matrix? // Disallow request as per matrix?
var block = µm.mustBlock(tabContext.rootHostname, details.hostname, 'doc'); var block = µm.mustBlock(tabContext.rootHostname, details.hostname, 'doc');
@ -215,19 +119,15 @@ var onBeforeRootFrameRequestHandler = function(details) {
} }
// Blocked // Blocked
var query = btoa(JSON.stringify({
url: requestURL,
hn: details.hostname,
why: '?'
}));
// If it's a blacklisted frame, redirect to frame.html
// rhill 2013-11-05: The root frame contains a link to noop.css, this
// allows to later check whether the root frame has been unblocked by the
// user, in which case we are able to force a reload using a redirect.
var html = rootFrameReplacement;
html = html.replace('{{cssURL}}', µm.noopCSSURL);
html = html.replace(/{{hostname}}/g, encodeURIComponent(requestHostname));
html = html.replace('{{originalURL}}', encodeURIComponent(requestURL));
html = html.replace('{{now}}', String(Date.now()));
var dataURI = 'data:text/html;base64,' + btoa(html);
return { 'redirectUrl': dataURI };
vAPI.tabs.replace(tabId, vAPI.getURL('main-blocked.html?details=') + query);
return { cancel: true };
}; };
/******************************************************************************/ /******************************************************************************/
@ -258,11 +158,6 @@ var onBeforeRequestHandler = function(details) {
var requestURL = details.url; var requestURL = details.url;
// Is it µMatrix's noop css file?
if ( requestType === 'css' && requestURL.lastIndexOf(µm.noopCSSURL, 0) === 0 ) {
return onBeforeChromeExtensionRequestHandler(details);
}
// Ignore non-http schemes // Ignore non-http schemes
if ( requestScheme.indexOf('http') !== 0 ) { if ( requestScheme.indexOf('http') !== 0 ) {
return; return;
@ -603,8 +498,7 @@ var requestTypeNormalizer = {
vAPI.net.onBeforeRequest = { vAPI.net.onBeforeRequest = {
urls: [ urls: [
"http://*/*", "http://*/*",
"https://*/*",
"chrome-extension://*/*"
"https://*/*"
], ],
extra: [ 'blocking' ], extra: [ 'blocking' ],
callback: onBeforeRequestHandler callback: onBeforeRequestHandler
@ -641,7 +535,6 @@ var start = function() {
/******************************************************************************/ /******************************************************************************/
return { return {
blockedRootFramePrefix: 'data:text/html;base64,' + btoa(rootFrameReplacement).slice(0, 80),
start: start start: start
}; };

72
src/main-blocked.html

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="css/common.css" type="text/css">
<style>
body {
font-family: sans-serif;
font-size: large;
text-align: center;
}
body > div {
margin: 1.5em 0;
}
body > div > p {
margin: 4px 0;
}
body > div > p:first-child {
margin: 1.5em 0 0 0;
}
.code {
background-color: rgba(0, 0, 0, 0.1);
display: inline-block;
font-family: monospace;
font-size: large;
line-height: 1;
padding: 2px 4px;
word-break: break-all;
}
button {
cursor: pointer;
margin: 0 1em 0.25em 1em;
padding: 0.25em 0.5em;
font-size: inherit;
}
#warningSign {
margin: 1e, 0;
opacity: 1;
pointer-events: none;
width: 100%;
}
#warningSign > span {
color: #f2a500;
font-size: 180px;
}
</style>
</head>
<body>
<div id="warningSign"><span class="fa">&#xf071;</span></div>
<div>
<p data-i18n="mainBlockedPrompt1"></p>
<p class="what code"></p>
</div>
<!-- <div>
<p data-i18n="mainBlockedPrompt2"></p>
<p id="why" class="code"></p>
</div>
-->
<div>
<p><button id="back" data-i18n="mainBlockedBack" type="button"></button>
<button id="bye" data-i18n="mainBlockedClose" type="button"></button></p>
</div>
<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/main-blocked.js"></script>
</body>
</html>
Loading…
Cancel
Save