190 lines
4.9 KiB
JavaScript
190 lines
4.9 KiB
JavaScript
|
const iconColorAndDesc = {
|
||
|
0: { color: "grey", desc: "Detect Cloudflare" },
|
||
|
1: { color: "green", desc: "This page doesn't seem to use Cloudflare." },
|
||
|
2: { color: "orange", desc: "External resources on this page use Cloudflare." },
|
||
|
3: { color: "red", desc: "This page uses Cloudflare!" }
|
||
|
};
|
||
|
|
||
|
function Counter() {
|
||
|
this.counts = new Map();
|
||
|
this.setCount = function(key,val) {
|
||
|
this.counts.set(key, val);
|
||
|
};
|
||
|
this.getCount = function(key) {
|
||
|
if (!this.counts.has(key)) { return 0; }
|
||
|
else { return this.counts.get(key); }
|
||
|
};
|
||
|
this.incCount = function(key) {
|
||
|
if (!this.counts.has(key)) { this.counts.set(key,1); }
|
||
|
else { this.counts.set(key, this.counts.get(key)+1); }
|
||
|
};
|
||
|
this.delCount = function(key) {
|
||
|
this.counts.delete(key);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function mapToObject( map ) {
|
||
|
obj = {};
|
||
|
map.forEach( function(val,key) { obj[key]=val; } );
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
function CFInfo() {
|
||
|
this.domainCounter = new Counter();
|
||
|
this.result = 0;
|
||
|
// maybe more in the future
|
||
|
}
|
||
|
|
||
|
function CFInfoByTab() {
|
||
|
this.info = new Map();
|
||
|
this.getInfo = function(id) {
|
||
|
return this.info.get(id);
|
||
|
}
|
||
|
this.getOrCreate = function(id) {
|
||
|
if (!this.info.has(id)) { this.info.set(id, new CFInfo()); }
|
||
|
return this.info.get(id);
|
||
|
};
|
||
|
this.delInfo = function(id) {
|
||
|
this.info.delete(id);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
var cfInfo = new CFInfoByTab();
|
||
|
|
||
|
function onError(e) {
|
||
|
console.log(`CF-Detect-Background: ${e}`);
|
||
|
}
|
||
|
|
||
|
function getDomainFromURL( urltxt ) {
|
||
|
try {
|
||
|
var url = new URL(urltxt);
|
||
|
return url.hostname;
|
||
|
} catch(err) {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function updateStatus( tabId ) {
|
||
|
var info = cfInfo.getInfo(tabId);
|
||
|
if (info) {
|
||
|
if (info.result >= 3) return; // no need for further updates
|
||
|
var counts = info.domainCounter.counts;
|
||
|
if (counts.size == 0) {
|
||
|
info.result = 1;
|
||
|
updateIcon( tabId, 1 );
|
||
|
} else {
|
||
|
chrome.tabs.get(tabId, function(tab) {
|
||
|
try {
|
||
|
var domain = getDomainFromURL(tab.url);
|
||
|
if (counts.has(domain)) {
|
||
|
info.result = 3;
|
||
|
updateIcon( tabId, 3 );
|
||
|
} else {
|
||
|
info.result = 2;
|
||
|
updateIcon( tabId, 2 );
|
||
|
}
|
||
|
} catch (error) {
|
||
|
onError(error);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
} else {
|
||
|
updateIcon( tabId, 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function updateIcon( tabId, result ) {
|
||
|
var cd = iconColorAndDesc[result];
|
||
|
var color = cd.color;
|
||
|
var title = cd.desc;
|
||
|
chrome.browserAction.setTitle({
|
||
|
tabId: tabId,
|
||
|
title: title
|
||
|
});
|
||
|
chrome.browserAction.setIcon({
|
||
|
tabId: tabId,
|
||
|
path: {
|
||
|
16: `icons/cf-${color}-16.png` ,
|
||
|
32: `icons/cf-${color}-32.png` ,
|
||
|
64: `icons/cf-${color}-64.png`
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function cfdetect( details ) {
|
||
|
var headers = details.responseHeaders;
|
||
|
var cf = false;
|
||
|
for (var i=0; i<headers.length; i++) {
|
||
|
var h = headers[i];
|
||
|
var hname = h.name.toLowerCase();
|
||
|
if ((hname === "cf-ray") ||
|
||
|
(hname === "server" && h.value === "cloudflare-nginx")) {
|
||
|
cf = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
var tabId = details.tabId;
|
||
|
if (tabId == -1) return;
|
||
|
var info = cfInfo.getOrCreate(tabId);
|
||
|
if (cf) {
|
||
|
var ctr = info.domainCounter;
|
||
|
var domain = getDomainFromURL( details.url );
|
||
|
ctr.incCount(domain);
|
||
|
}
|
||
|
updateStatus(tabId);
|
||
|
}
|
||
|
|
||
|
function handleBeforeNavigate( details ) {
|
||
|
if (details.frameId == 0) {
|
||
|
cfInfo.delInfo( details.tabId );
|
||
|
updateStatus( details.tabId );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function handleTabUpdate( tabId, changeInfo, tabInfo ) {
|
||
|
if ("url" in changeInfo) {
|
||
|
updateStatus( tabId );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function handleTabClose( tabId, removeInfo ) {
|
||
|
cfInfo.delInfo(tabId);
|
||
|
}
|
||
|
|
||
|
function handleTabReplace( newId, oldId ) {
|
||
|
cfInfo.delInfo(oldId);
|
||
|
}
|
||
|
|
||
|
// triggered by popup script
|
||
|
function handleConnect(port) {
|
||
|
port.onMessage.addListener( function(tabId) {
|
||
|
var info = cfInfo.getInfo(tabId);
|
||
|
var msg;
|
||
|
if (info) {
|
||
|
msg = {
|
||
|
result: info.result,
|
||
|
counts: mapToObject(info.domainCounter.counts)
|
||
|
};
|
||
|
} else {
|
||
|
msg = null;
|
||
|
}
|
||
|
port.postMessage(msg);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
chrome.webRequest.onHeadersReceived.addListener(
|
||
|
cfdetect,
|
||
|
{ urls: [ "<all_urls>" ] },
|
||
|
[ "responseHeaders" ]
|
||
|
);
|
||
|
|
||
|
chrome.webNavigation.onBeforeNavigate.addListener( handleBeforeNavigate );
|
||
|
|
||
|
chrome.tabs.onUpdated.addListener( handleTabUpdate );
|
||
|
chrome.tabs.onRemoved.addListener( handleTabClose );
|
||
|
chrome.tabs.onReplaced.addListener( handleTabReplace );
|
||
|
|
||
|
chrome.runtime.onConnect.addListener( handleConnect );
|
||
|
|
||
|
// vim: set expandtab ts=4 sw=4 :
|