// ==UserScript==
// @name WebSuckIt!
// @namespace lainscripts_websuckit
// @version 4.1
// @description Ugh, these Webs these Sockets... Nobody need them.
// @author lainverse
// @match *://*/*
// @grant unsafeWindow
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
var win = unsafeWindow||window;
function WebSocketWrapper() {
// check if the browser supports Proxy and WebSocket
if (typeof Proxy !== 'function' ||
typeof WebSocket !== 'function') {
return;
}
var to_block = [
'||adlabs.ru',
'||bgrndi.com^',
'||brokeloy.com^',
'||dreadfula.ru^',
'||et-code.ru^',
'||free-torrent.org^',
'||free-torrents.org^',
'||game-torrent.info^',
'||gocdn.ru^',
'||hghit.com^',
'||kinotochka.net^',
'||kuveres.com^',
'||lepubs.com^',
'||luxup.ru^',
'||mail.ru^',
'||marketgid.com^',
'||mxtads.com^',
'||oconner.biz^',
'||poolnoodle.tech',
'||psma01.com^',
'||psma02.com^',
'||psma03.com^',
'||recreativ.ru^',
'||regpole.com^',
'||skidl.ru^',
'||torvind.com^',
'||trafmag.com^',
'||xxuhter.ru^',
'||yuiout.online^'
];
var masks = [];
to_block.forEach(function(m){
masks.push(new RegExp(
m.replace(/([\\\/\[\].*+?(){}$])/g, '\\$1')
.replace(/\^(?!$)/g,'\\.?[^\\w%._-]')
.replace(/\^$/,'\\.?([^\\w%._-]|$)')
.replace(/^\|\|/,'^wss?:\\/+([^\/.]+\\.)*'),
'i'));
});
var realWS = win.WebSocket,
closingFunctions = ['close', 'send'];
function wsGetter(tgt, nm) {
console.log('[WSI] Registered call to property "', nm, '"');
try {
if (typeof realWS.prototype[nm] === 'function') {
if (closingFunctions.indexOf(nm) > -1) {
tgt.readyState = realWS.CLOSED;
}
return function(){return;};
}
if (typeof realWS.prototype[nm] === 'number') {
return realWS[nm];
}
} catch(ignore) {}
return tgt[nm];
}
win.WebSocket = (new Proxy(realWS, {
construct: function(target, args) {
var url = args[0];
console.log('[WSI] Opening socket on', url, '…');
var i = masks.length;
while(i--) {
if (masks[i].test(url)) {
console.log("[WSI] Blocked.");
return new Proxy({url: url, readyState: realWS.OPEN}, {
get: wsGetter
});
}
}
return new target(args[0], args[1]);
}
}));
}
function WorkerWrapper(){
var wr = win.Worker;
win.Worker = function(resourceURI) {
var _promise = new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.open('GET', resourceURI, true);
xhr.responseType = 'blob';
xhr.onload = function(){
if (this.status == 200) {
var reader = new FileReader();
reader.addEventListener("loadend", function() {
resolve(
new wr(
URL.createObjectURL(
new Blob(['(function(){var win = self;'+
WebSocketWrapper.toString()+
' WebSocketWrapper();})();'+this.result])
)
)
);
});
reader.readAsText(this.response);
}
};
xhr.send();
});
var _worker = null,
_terminate = false,
_onerror = null,
_onmessage = null,
_messages = [],
_events = [];
var setWorker = function(val) {
_worker = val;
_worker.onerror = _onerror;
_worker.onmessage = _onmessage;
if (_terminate) {
_worker.terminate();
}
while(_messages.length) {
_worker.postMessage(_messages.shift());
}
while(_events.length) {
_worker.addEventListener.apply(_worker, _events.pop());
}
};
_promise.then(setWorker);
this.terminate = function(){
_terminate = true;
if (_worker) {
_worker.terminate();
}
};
Object.defineProperty(this, 'onmessage', {
get:function(){
return _onmessage;
},
set:function(val){
_onmessage = val;
if (_worker) {
_worker.onmessage = val;
}
}
});
Object.defineProperty(this, 'onerror', {
get:function(){
return _onerror;
},
set:function(val){
_onerror = val;
if (_worker) {
_worker.onmessage = val;
}
}
});
this.postMessage = function(message){
if (_worker) {
_worker.postMessage(message);
} else {
_messages.push(message);
}
};
this.terminate = function() {
_terminate = true;
if (_worker) {
_worker.terminate();
}
};
this.addEventListener = function(){
if (_worker) {
_worker.addEventListener.apply(_worker, arguments);
} else {
_events.push(arguments);
}
};
this.removeEventListener = function(){
if (_worker) {
_worker.removeEventListener.apply(_worker, arguments);
} // I don't think I should care to remove events here,
// normally it shouldn't be invoked before _worker is created
};
};
}
if (/firefox/i.test(navigator.userAgent)) {
var script = document.createElement('script');
var WSIstr = '(function(){var win = self||window;'+
WebSocketWrapper.toString() +
WorkerWrapper.toString() +
'WebSocketWrapper();WorkerWrapper();})();';
script.appendChild(
document.createTextNode(WSIstr + 'if (document.currentScript) {'+
'document.currentScript.parentNode.removeChild(document.currentScript);'+
'}')
);
(document.head || document.body || document.documentElement).appendChild(script);
return; //exit
}
WebSocketWrapper();
WorkerWrapper();
})();