Files
MINResolveV2/background.js
T

760 lines
25 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* The background script to handle url redirection.
*/
var storage = null;
var downloading = false;
var downloadTimer = null;
// 存储MIS的IP
var misHost="121.15.171.92";
// 请求映射表项时兴趣包使用的前缀
var misPrefix="/mis/resolve";
// 兴趣包前缀序号
var misPrefixNum=0;
// 是否开启mis更新映射表
var misEnableState=true;
// 获取兴趣包前缀
function getInterestPrefix() {
misPrefixNum++;
browser.storage.local.set({'misPrefixNum':misPrefixNum});
return misPrefix+'/'+misPrefixNum;
}
// 加载mis的IP
function loadMisHost() {
browser.storage.local.get('misHostIP',function (result) {
if($.isEmptyObject(result)){
// alert("hostIP: null");
browser.storage.local.set({'misHostIP':misHost});
}else{
// alert("hostIP: "+result.misHostIP);
misHost=result.misHostIP;
}
});
browser.storage.local.get('misPrefix',function (result) {
if($.isEmptyObject(result)){
// alert("misPrefix: null");
browser.storage.local.set({'misPrefix':misPrefix});
}else{
// alert("misPrefix: "+result.misPrefix);
misPrefix=result.misPrefix;
}
});
browser.storage.local.get('misPrefixNum',function (result) {
if($.isEmptyObject(result)){
// alert("misPrefix: null");
browser.storage.local.set({'misPrefixNum':misPrefixNum});
}else{
// alert("misPrefix: "+result.misPrefix);
misPrefixNum=result.misPrefixNum;
}
});
browser.storage.local.get('misEnableState',function (result) {
if($.isEmptyObject(result)){
// alert("misPrefix: null");
browser.storage.local.set({'misEnableState':misEnableState});
}else{
// alert("misPrefix: "+result.misPrefix);
misEnableState=result.misEnableState;
// alert("48641");
}
});
}
/* Reload callback */
function reload(result) {
storage = new Storage();
if (result && result.storage) {
storage.fromObject(result.storage);
resetDownloadTimer();
}
}
/* Auto reload */
browser.storage.onChanged.addListener(function (changes, area) {
// if (area == "local") {
load("storage", reload);
loadMisHost();
// }
});
/* The first time of loading storage */
load("storage", reload);
loadMisHost();
// alert("成功加载mis的IP: "+misHost+"; misPrefix: "+misPrefix);
function getJsonString(u_identifier){
var jsonObj={
"Type":"user-act",
"Command":"Resolve",
"QueryCode":2,
"U_identifier":u_identifier
};
// return jsonObj;
return JSON.stringify(jsonObj);
}
function onData(interest, data)
{
// printLine("Got data packet with name " + data.getName().toUri());
// printLine(data.getContent().buf().toString('binary'));
}
function onTimeout(interest)
{
// printLine("Time out for interest " + interest.getName().toUri());
}
// 增加映射表项时,判断该表项是否重复
function addCustomRule(editingRule) {
var flag=0;
for (var i=0; i<storage.customRules.length; i++) {
var rule = storage.customRules[i];
if ((rule.origin === editingRule.origin) && (rule.target === editingRule.target)) {
flag=1;
}
}
if(flag===0){
storage.customRules.push(editingRule);
}
}
function express(prefixUri) {
// alert("成功加载mis的IP: "+misHost+"; misPrefix: "+misPrefix);
var host = misHost;
// Connect to the forwarder with a WebSocket.
var face = new Face({host: host});
var name = new Name(getInterestPrefix());
var interest=new Interest(name);
interest.setMustBeFresh(true);
var jsonPrefix=getJsonString(prefixUri);
interest.setApplicationParameters(new Blob(jsonPrefix));
interest.setInterestLifetimeMilliseconds(2000);
// alert("express Interest: "+jsonPrefix);
// printLine("Express interest " + interest.getName().toUri());
// printLine("The json string is "+interest.getApplicationParameters().toString());
face.expressInterest(interest, function(interest,data){
var targetJsonString=data.getContent().buf().toString('binary');
// alert("targetJsonString: "+targetJsonString);
var targetJson=JSON.parse(targetJsonString);
// 将targetJson解析成targetUri
var StatusCode=targetJson.StatusCode;
var targetUri=targetJson.Message;
if((StatusCode===200)&&(targetUri!=="")) {
var editingRule = new Rule();
editingRule.enable = true;
editingRule.description = "initial based on MIS";
editingRule.origin = prefixUri;
editingRule.target = targetUri;
editingRule.exclude = "";
editingRule.example = "";
editingRule.process = "";
editingRule.methods = [];
editingRule.types = [];
// storage.customRules.push(editingRule);
addCustomRule(editingRule);
/* save */
save({"storage": storage});
load("storage", reload);
}else{
// mis没有该前缀对应的映射
}
// alert("really begin 4");
}, onTimeout);
}
/* ini storage based on the MIS System */
// function iniStorageBasedMIS() {
// // alert("really begin");
// var prefixUri="/mis/baidu";
// express(prefixUri);
// }
// alert("begin reset");
// iniStorageBasedMIS();
/* Download online rules */
function downloadOnlineURLs() {
/* Still downloading */
if (!storage.onlineURLs || storage.onlineURLs.length <=0 || downloading) {
return;
}
downloading = true;
var toDownload = []; // URLs that need to be downloaded
for (var i = 0; i < storage.onlineURLs.length; i++) {
var onlineURL = storage.onlineURLs[i];
if (onlineURL.auto && onlineURL.enable && onlineURL.url !== "") {
toDownload.push(onlineURL.url);
}
}
if (toDownload.length === 0) {
sendMessage("downloaded");
}
var downloadErrors = [];
var parseErrors = [];
for (var i = 0; i<toDownload.length; i++) {
download(toDownload[i], function (url, content) {
toDownload.remove(url);
if (content) {
try {
var json;
// content may be a string or json object
if (typeof content === "string") {
json = JSON.parse(content);
} else {
json = content;
}
json.url = url;
json.enable = true;
json.downloadAt = new Date();
/* To compact with gooreplacer */
/* version < 1.0, version >= 1.0 doesn't change */
if (!json.version || json.version < "1.0") {
var rules = [];
for (var key in json.rules) {
var rule = json.rules[key];
rules.push({
origin: key,
target: rule.dstURL,
enable: rule.enable === undefined ? true : rule.enable,
kind: rule.kind
});
}
json.rules = rules;
}
/* replace the onlineURL */
for (var j = 0; j < storage.onlineURLs.length; j++){
if (storage.onlineURLs[j].url == url){
storage.onlineURLs[j] = new OnlineURL();
storage.onlineURLs[j].fromObject(json);
break;
}
}
} catch (err) {
parseErrors.push(url);
console.error(err);
}
}
else {
downloadErrors.push(url);
}
if (toDownload.length <= 0) {
downloading = false;
sendMessage("downloaded");
if (downloadErrors.length > 0) {
sendMessage("downloadError", downloadErrors);
}
if (parseErrors.length > 0) {
sendMessage("parseError", parseErrors);
}
storage.updatedAt = (new Date()).toISOString();
save({"storage": storage});
}
});
}
}
/* Reset download timer to download online urls */
/* Setup a listener if alarm api supported */
if (browser.alarms) {
browser.alarms.onAlarm.addListener(function (alarm) {
if (alarm.name == "download") {
downloadOnlineURLs();
}
})
}
/* Reset the download timer */
function resetDownloadTimer() {
var interval = 900; // Default 15min
if (storage.updateInterval) {
interval = parseInt(storage.updateInterval);
}
/* If the browser support alarms api */
if (browser.alarms) {
browser.alarms.create("download", {
periodInMinutes: Math.ceil(interval / 60)
});
}
else {
/* With setInterval */
if (downloadTimer != null) {
clearInterval(downloadTimer);
}
interval = interval * 1000; // In milli-seconds
downloadTimer = setInterval(function () {
if (storage.enable) {
downloadOnlineURLs();
}
}, interval);
}
}
/* Handle runtime messages */
browser.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.method == "download" && !downloading) {
downloadOnlineURLs();
}
else if (message.method == "isDownloading") {
sendResponse(downloading);
}
else {
console.error("Unknown method");
}
});
function redirect(details) {
if (storage.enable && details.url) {
var newURL = storage.redirect(details.url, details.method, details.type);
if (newURL){
return {
redirectUrl: newURL
}
}
}
return {};
}
var _redirect_promise_supported = false;
// 判断某个字符串是否是一个搜索url
function isSearchUrl(urlString){
var searchLibs=[
// 百度
"https://www.baidu.com",
"http://www.baidu.com",
// 谷歌
"https://www.google.com",
"http://www.google.com",
// 搜狗
"https://www.sogou.com",
"http://www.sogou.com",
// 360
"https://www.so.com",
"http://www.so.com",
// bing
"https://cn.bing.com",
"http://cn.bing.com"
];
var flag=0;
for(var i=0;i<searchLibs.length;i++){
if(urlString.indexOf(searchLibs[i])>=0){
flag=1;
break;
}
}
var haveSearchString=getPositiveNum(urlString.indexOf("?wd="))
+getPositiveNum(urlString.indexOf("&wd="))
+getPositiveNum(urlString.indexOf("?q="))
+getPositiveNum(urlString.indexOf("&q="))
+getPositiveNum(urlString.indexOf("?query="))
+getPositiveNum(urlString.indexOf("&query="));
if((flag>0)&&(haveSearchString>0)){
// alert("it is a searchUrl: "+urlString);
return true;
}else{
return false;
}
}
// 对小于0的数取0
function getPositiveNum(num) {
if(num>0){
return num;
}else{
return 0;
}
}
// 传入一个搜索uri,获取其中的搜索数值
function getSearchContent(uriString) {
if(!isSearchUrl(uriString)){
return "";
}
var content="";
if(uriString.indexOf("//www.baidu.com")>=0){
// &wd= [end] 或 &wd= &
var startIndex=getPositiveNum(uriString.indexOf("?wd="))
+getPositiveNum(uriString.indexOf("&wd="))+4;
var lastString=uriString.substring(startIndex);
var endIndex=lastString.indexOf('&');
if(endIndex>=0){
content=lastString.substring(0,endIndex);
}else{
content=lastString;
}
}else if(uriString.indexOf("//www.google.com")>=0){
// ?q= &
var startIndex=getPositiveNum(uriString.indexOf("?q="))
+getPositiveNum(uriString.indexOf("&q="))+3;
var lastString=uriString.substring(startIndex);
var endIndex=lastString.indexOf('&');
if(endIndex>=0){
content=lastString.substring(0,endIndex);
}else{
content=lastString;
}
}else if(uriString.indexOf("//www.sogou.com")>=0){
// &query= [end]
var startIndex=getPositiveNum(uriString.indexOf("?query="))
+getPositiveNum(uriString.indexOf("&query="))+7;
var lastString=uriString.substring(startIndex);
var endIndex=lastString.indexOf('&');
if(endIndex>=0){
content=lastString.substring(0,endIndex);
}else{
content=lastString;
}
}else if(uriString.indexOf("//www.so.com")>=0){
// &q= [end]
var startIndex=getPositiveNum(uriString.indexOf("?q="))
+getPositiveNum(uriString.indexOf("&q="))+3;
var lastString=uriString.substring(startIndex);
var endIndex=lastString.indexOf('&');
if(endIndex>=0){
content=lastString.substring(0,endIndex);
}else{
content=lastString;
}
}else if(uriString.indexOf("//cn.bing.com")>=0){
// q= &
var startIndex=getPositiveNum(uriString.indexOf("?q="))
+getPositiveNum(uriString.indexOf("&q="))+3;
var lastString=uriString.substring(startIndex);
var endIndex=lastString.indexOf('&');
if(endIndex>=0){
content=lastString.substring(0,endIndex);
}else{
content=lastString;
}
}else{}
return content.replace(/%2F/g,'/');
}
// 判断某个字符串是否包含映射表中的表项
function isIncludedRules(urlString) {
var flag=0;
for (var i=0; i<storage.customRules.length; i++) {
var rule = storage.customRules[i];
var afterDecodeOrigin=rule.origin.replace('/','%2F');
if ((urlString.indexOf(rule.origin)>=0)||(urlString.indexOf(afterDecodeOrigin)>=0)) {
flag=1;
break;
}
}
if(flag===0){
// alert("it do not includes rules");
return false;
}else{
// alert("it includes rules");
// console.log("it includes rules");
return true;
}
}
// 模糊判断一个string是否是一个合法前缀
function isRightfulPrefix(urlString){
if(urlString===''){
return false;
}
if(urlString.indexOf('.')>=0){
return false;
}
if((urlString.indexOf('/')!==0)&&(urlString.indexOf('%2F')!==0)){
// alert("没/");
return false;
}
return true;
}
// 判断某个字符串是否是映射表的一个前缀表项
// 判断某个字符串是否包含映射表中的表项
function isRulesPrefix(urlString) {
// alert("要判断的urlString: "+urlString);
// 先进行模糊判断
// if(urlString===''){
// return false;
// }
// if(urlString.indexOf('.')>=0){
// return false;
// }
// if((urlString.indexOf('/')!==0)&&(urlString.indexOf('%2F')!==0)){
// // alert("没/");
// return false;
// }
if(!isRightfulPrefix(urlString)){
return false;
}
// 再遍历本地映射表
var flag=0;
for (var i=0; i<storage.customRules.length; i++) {
var rule = storage.customRules[i];
var afterDecodeOrigin=rule.origin.replace('/','%2F');
if ((urlString===rule.origin)||(urlString===afterDecodeOrigin)) {
flag=1;
break;
}
}
if(flag===0){
// alert("it do not includes rules");
return false;
}else{
// alert("it includes rules");
// console.log("it includes rules");
return true;
}
}
// 判断某个字符串是在搜索映射表表项
function isSearchForRules(urlString) {
if(isSearchUrl(urlString)&&isIncludedRules(urlString)){
// console.log("it is searching for rules!!!");
return true;
}else{
return false;
}
}
// 获取url中包括的rule.origin
function getIncludedRules(urlString) {
var flag=0;
var originString="";
for (var i=0; i<storage.customRules.length; i++) {
var rule = storage.customRules[i];
var afterDecodeOrigin=rule.origin.replace('/','%2F');
if ((urlString.indexOf(rule.origin)>=0)||(urlString.indexOf(afterDecodeOrigin)>=0)) {
flag=1;
originString=rule.origin;
break;
}
}
return originString;
}
// 剪切不包含.这个字符的URI的http头
function cutHttpHead(uri) {
// 判断是http:还是https:
var startIndex=0;
if(uri.indexOf("https:")>=0){
startIndex=8;
}else if(uri.indexOf("http:")>=0){
startIndex=7;
}
// 判断uri中是否含有.这个字符
if(uri.indexOf('.')>=0){
return "";
}else{
var uritmp=uri.substr(startIndex);
if(uritmp.indexOf(0)==='/'){
return uritmp;
}else{
return '/'+uritmp;
}
}
}
// 根据传入的uri获取前缀,从而更新本地映射表
function updateStorageBasedUri(uri) {
// alert("begin upgrate");
var uriCut=cutHttpHead(uri);
// alert("uricut: "+uriCut);
if(uriCut===""){
}else{
express(uriCut);
}
}
// 根据传入的前缀,更新本地映射表
function updateStorageBasedPrefix(prefix) {
express(prefix);
}
/* Handle redirect */
function handleRedirect(details) {
// 判断url是否是一个搜索url,并根据搜索内容,判断是否直接命中本地映射表
var searchContent=getSearchContent(details.url);
// alert("sc: "+searchContent);
// 判断url去掉头部之后是否直接命中本地映射表
var cutHeadString=cutHttpHead(details.url);
// 如果该搜索内容或网址命中了缓存中的映射表前缀,则重定向
if(isRulesPrefix(searchContent)||isRulesPrefix(cutHeadString)){
// alert("sc: "+searchContent+" isRules: "+isRulesPrefix(searchContent));
// alert("cut: "+cutHeadString+" isRules: "+isRulesPrefix(cutHeadString));
var prefixTemp="";
if(searchContent!==""){
prefixTemp=searchContent;
}else{
prefixTemp=cutHeadString;
}
details.url = "http://" + prefixTemp;
// alert("detail-url: "+details.url);
if (_redirect_promise_supported) {
var promise = new Promise(function (resolve, reject) {
var blockingResponse = redirect(details);
return resolve(blockingResponse);
});
return promise;
} else {
// alert("redirect: "+details.url);
return redirect(details);
}
}
// 如果没有命中缓存映射表,但是它是一个检索内容的网址,
// 则根据该内容更新本地缓存之后,进行重定向
if(searchContent!==""){
// alert("检索内容了呢:"+searchContent);
if ((misEnableState === true)&&isRightfulPrefix(searchContent)) {
// 如果检索内容模糊判断是一个前缀,且mis同步是开着的
// alert("成功加载mis的IP: "+misHost+"; misPrefix: "+misPrefix);
var host = misHost;
// Connect to the forwarder with a WebSocket.
var face = new Face({host: host});
var name = new Name(getInterestPrefix());
var interest=new Interest(name);
interest.setMustBeFresh(true);
var jsonPrefix=getJsonString(searchContent);
interest.setApplicationParameters(new Blob(jsonPrefix));
interest.setInterestLifetimeMilliseconds(2000);
// alert("express Interest");
face.expressInterest(interest, function(interest,data){
var targetJsonString=data.getContent().buf().toString('binary');
// alert("targetJsonString: "+targetJsonString);
var targetJson=JSON.parse(targetJsonString);
// 将targetJson解析成targetUri
var StatusCode=targetJson.StatusCode;
var targetUri=targetJson.Message;
// alert("code: "+StatusCode+", "+targetUri);
if((StatusCode===200)&&(targetUri!=="")) {
var editingRule = new Rule();
editingRule.enable = true;
editingRule.description = "initial based on MIS";
editingRule.origin = searchContent;
editingRule.target = targetUri;
editingRule.exclude = "";
editingRule.example = "";
editingRule.process = "";
editingRule.methods = [];
editingRule.types = [];
// storage.customRules.push(editingRule);
addCustomRule(editingRule);
/* save */
save({"storage": storage});
load("storage", reload);
// alert("已经重新更新了本地映射表");
// 缓存映射表更新之后,执行重定向操作
details.url = "http://" + searchContent;
}
// alert("根据本地缓存要重定向了哦");
if (_redirect_promise_supported) {
var promise = new Promise(function (resolve, reject) {
var blockingResponse = redirect(details);
return resolve(blockingResponse);
});
return promise;
} else {
// alert("deurl: "+details.url);
return redirect(details);
}
}, function (interest) {
// alert("time out...");
// mis系统崩溃,没有给任何应答,直接执行重定向操作
if (_redirect_promise_supported) {
var promise = new Promise(function (resolve, reject) {
var blockingResponse = redirect(details);
return resolve(blockingResponse);
});
return promise;
} else {
return redirect(details);
}
});
}else{
// 直接尝试重定向
if (_redirect_promise_supported) {
var promise = new Promise(function (resolve, reject) {
var blockingResponse = redirect(details);
return resolve(blockingResponse);
});
return promise;
} else {
return redirect(details);
}
}
}else{
// 如果不是进行搜索,且本地没有命中映射表,则异步请求mis更新映射表
if((misEnableState===true)&&isRightfulPrefix(cutHeadString)){
updateStorageBasedUri(details.url);
}
// 并进行重定向
if (_redirect_promise_supported) {
var promise = new Promise(function (resolve, reject) {
var blockingResponse = redirect(details);
return resolve(blockingResponse);
});
return promise;
} else {
return redirect(details);
}
}
}
// /* Handle redirect */
// function handleRedirect(details) {
// // alert("misEnableState: " + misEnableState);
// // alert("detail-url: "+details.url);
// if(isSearchUrl(details.url)){
// if (misEnableState === true) {
// updateStorageBasedUri(details.url);
// }
// }
// // 判断是否是搜索映射表表项,如果是,直接跳转到映射界面
// if(isSearchForRules(details.url)){
// // alert("捕获到了一个前缀搜索: "+details.url);
// details.url="http://"+getIncludedRules(details.url);
// // alert("B-url: "+details.url);
// }else{
// if (misEnableState === true) {
// updateStorageBasedUri(details.url);
// }
// }
//
// if (_redirect_promise_supported) {
// var promise = new Promise(function (resolve, reject) {
// var blockingResponse = redirect(details);
// return resolve(blockingResponse);
// });
// // alert("修改后的details.url-0: "+details.url);
// // history.pushState({},"Wow Title","/my/awesome/url");
// return promise;
// } else {
// // history.pushState({},"Wow Title","/my/awesome/url");
// // alert("修改后的details.url-1: "+details.url);
// return redirect(details);
// }
// }
/* Since firefox 52, could return a promise to handles asynchronously */
if (browser.runtime.getBrowserInfo) {
function checkRedirectPromise(info) {
if (info.name == "Firefox") {
if (parseInt(info.version.split('.')[0]) >= 52) {
_redirect_promise_supported = true;
}
}
}
var gettingInfo = browser.runtime.getBrowserInfo();
gettingInfo.then(checkRedirectPromise)
}
/* Add listener */
browser.webRequest.onBeforeRequest.addListener(
handleRedirect,
{urls: ["<all_urls>"]},
["blocking"]
);