web-api-manager/background_scripts/background.js
Peter Snyder b87002c7a1 buta
2017-10-14 13:52:56 -05:00

132 lines
No EOL
4.2 KiB
JavaScript

/*jslint es6: true*/
/*global chrome, browser, window, URI*/
(function () {
const {packingLib, standards, storageLib} = window.WEB_API_MANAGER;
const rootObject = window.browser || window.chrome;
const defaultKey = "(default)";
// Once loaded from storage, will be a mapping from regular expressions
// (or the default option, "(default)"), to an array of standards
// that should be blocked on matching domains.
let domainRules;
storageLib.get(function (loadedDomainRules) {
domainRules = loadedDomainRules;
});
// Manage the state of the browser activity, by displaying the number
// of origins / frames
const updateBrowserActionBadge = function (activeInfo) {
const {tabId, windowId} = activeInfo;
rootObject.tabs.executeScript(
tabId,
{
allFrames: true,
code: "window.location.host"
},
function (allHosts) {
if (rootObject.runtime.lastError) {
rootObject.browserAction.disable(tabId);
return;
}
rootObject.browserAction.enable(tabId);
const numFrames = allHosts
? Array.from(new Set(allHosts)).length.toString()
: "";
rootObject.browserAction.setBadgeText({
text: numFrames,
tabId: tabId
});
}
);
};
rootObject.tabs.onUpdated.addListener(updateBrowserActionBadge);
rootObject.tabs.onActivated.addListener(updateBrowserActionBadge);
rootObject.windows.onFocusChanged.addListener(updateBrowserActionBadge);
// Inject the blocking settings for each visited domain / frame.
const extractHostFromUrl = function (url) {
const uri = URI(url);
return uri.hostname();
};
const matchingUrlReduceFunction = function (domain, prev, next) {
if (prev) {
return prev;
}
const domainRegex = new RegExp(next);
if (domainRegex.test(domain)) {
return next;
}
return prev;
};
const whichDomainRuleMatches = function (hostName) {
// of the URL being requested.
const matchingUrlReduceFunctionBound = matchingUrlReduceFunction.bind(undefined, hostName);
const matchingPattern = Object
.keys(domainRules)
.filter((aRule) => aRule !== defaultKey)
.sort()
.reduce(matchingUrlReduceFunctionBound, undefined);
return matchingPattern || defaultKey;
};
// Listen for updates to the domain rules from the config page.
rootObject.runtime.onMessage.addListener(function (request, sender, sendResponse) {
const [label, data] = request;
if (label === "rulesUpdate") {
domainRules = data;
return;
}
if (label === "rulesForDomains") {
const ruleForDomain = data.map(whichDomainRuleMatches);
const mapping = {};
for (let i = 0; i < ruleForDomain.length; i += 1) {
mapping[data[i]] = ruleForDomain[i];
}
sendResponse(mapping);
return;
}
});
const requestFilter = {
urls: ["<all_urls>"],
types: ["main_frame", "sub_frame"]
};
const requestOptions = ["blocking", "responseHeaders"];
chrome.webRequest.onHeadersReceived.addListener(function (details) {
const url = details.url;
const hostName = extractHostFromUrl(url);
// Decide which set of blocking rules to use, depending on the host
// of the URL being requested.
const matchingDomainKey = whichDomainRuleMatches(hostName);
const standardsToBlock = domainRules[matchingDomainKey];
const options = Object.keys(standards);
const packedValues = packingLib.pack(options, standardsToBlock);
details.responseHeaders.push({
name: "Set-Cookie",
value: `web-api-manager=${packedValues}`
});
return {
responseHeaders: details.responseHeaders
};
}, requestFilter, requestOptions);
}());