/**
* 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;
})();