Stateless-compatibile TabGuard.
This commit is contained in:
parent
95da855ff5
commit
6344d120cb
|
@ -18,23 +18,62 @@
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// depends on /nscl/common/SessionCache.js
|
||||||
|
// depends on /nscl/service/TabCache.js
|
||||||
|
// depends on /nscl/service/TabTies.js
|
||||||
|
|
||||||
var TabGuard = (() => {
|
var TabGuard = (() => {
|
||||||
(async () => { await include(["/nscl/service/TabCache.js", "/nscl/service/TabTies.js"]); })();
|
|
||||||
|
|
||||||
const anonymizedTabs = new Map();
|
let anonymizedTabs = new Map();
|
||||||
browser.tabs.onRemoved.addListener(tab => {
|
browser.tabs.onRemoved.addListener(({id}) => {
|
||||||
anonymizedTabs.delete(tab.id);
|
if (anonymizedTabs.has(id)) {
|
||||||
|
anonymizedTabs.delete(id);
|
||||||
|
session.save();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const anonymizedRequests = new Set();
|
const anonymizedRequests = new Set(); // ephemeral, lifespan is webRequest
|
||||||
|
|
||||||
let allowedGroups, filteredGroups;
|
// Domain groups:
|
||||||
let forget = () => {
|
// property keys are domains, property values are domain Sets
|
||||||
allowedGroups = {};
|
// (session-persisted)
|
||||||
filteredGroups = {};
|
|
||||||
|
let Groups = {
|
||||||
|
allowed: {},
|
||||||
|
filtered: {},
|
||||||
};
|
};
|
||||||
forget();
|
const forget = () => {
|
||||||
|
Groups.allowed = {};
|
||||||
|
Groups.filtered = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
const groupsSerDe = (source, callback) => {
|
||||||
|
const target = {};
|
||||||
|
for (const [which, group] of Object.entries(source)) {
|
||||||
|
const targetGroup = {};
|
||||||
|
for (const [domain, otherDomains] of Object.entries(group)) {
|
||||||
|
targetGroup[domain] = callback(otherDomains);
|
||||||
|
}
|
||||||
|
target[which] = targetGroup;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
const session = new SessionCache(
|
||||||
|
"TabGuard", // storageKey
|
||||||
|
{
|
||||||
|
afterLoad(data) { // afterLoad
|
||||||
|
if (!data) return;
|
||||||
|
anonymizedTabs = new Map(data.anonymizedTabs);
|
||||||
|
Groups = groupsSerDe(data.Groups, domainsArray => new Set(domainsArray));
|
||||||
|
},
|
||||||
|
beforeSave() {
|
||||||
|
return {
|
||||||
|
anonymizedTabs: [...anonymizedTabs],
|
||||||
|
Groups: groupsSerDe(Groups, domainsSet => [...domainsSet]),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function mergeGroups(groups,
|
function mergeGroups(groups,
|
||||||
{tabDomain, otherDomains}, /* anonymizedTabInfo */
|
{tabDomain, otherDomains}, /* anonymizedTabInfo */
|
||||||
|
@ -48,6 +87,7 @@ var TabGuard = (() => {
|
||||||
(groups[d] || (groups[d] = new Set())).add(tabDomain);
|
(groups[d] || (groups[d] = new Set())).add(tabDomain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
session.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
const AUTH_HEADERS_RX = /^(?:authorization|cookie)/i;
|
const AUTH_HEADERS_RX = /^(?:authorization|cookie)/i;
|
||||||
|
@ -65,9 +105,10 @@ var TabGuard = (() => {
|
||||||
return flat;
|
return flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
let scheduledCuts = new Set();
|
const scheduledCuts = new Set();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
wakening: Promise.all([TabCache.wakening, TabTies.wakening, session.load()]),
|
||||||
forget,
|
forget,
|
||||||
// must be called from a webRequest.onBeforeSendHeaders blocking listener
|
// must be called from a webRequest.onBeforeSendHeaders blocking listener
|
||||||
onSend(request) {
|
onSend(request) {
|
||||||
|
@ -199,7 +240,7 @@ var TabGuard = (() => {
|
||||||
suspiciousDomains.push(getDomain(tab.url));
|
suspiciousDomains.push(getDomain(tab.url));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const legitDomains = allowedGroups[tabDomain] || new Set();
|
const legitDomains = Groups.allowed[tabDomain] || new Set();
|
||||||
legitDomains.add(tabDomain);
|
legitDomains.add(tabDomain);
|
||||||
|
|
||||||
let otherDomains = new Set(suspiciousDomains.filter(d => d && !legitDomains.has(d)));
|
let otherDomains = new Set(suspiciousDomains.filter(d => d && !legitDomains.has(d)));
|
||||||
|
@ -213,11 +254,13 @@ var TabGuard = (() => {
|
||||||
requestHeaders = requestHeaders.filter(h => !AUTH_HEADERS_RX.test(h.name));
|
requestHeaders = requestHeaders.filter(h => !AUTH_HEADERS_RX.test(h.name));
|
||||||
debug("[TabGuard] Removing auth headers from %o (%o)", request, requestHeaders);
|
debug("[TabGuard] Removing auth headers from %o (%o)", request, requestHeaders);
|
||||||
anonymizedTabs.set(tabId, {tabDomain, otherDomains: [...otherDomains]});
|
anonymizedTabs.set(tabId, {tabDomain, otherDomains: [...otherDomains]});
|
||||||
|
session.save();
|
||||||
|
|
||||||
anonymizedRequests.add(request.id);
|
anonymizedRequests.add(request.id);
|
||||||
return {requestHeaders};
|
return {requestHeaders};
|
||||||
};
|
};
|
||||||
|
|
||||||
let quietDomains = filteredGroups[tabDomain];
|
let quietDomains = Groups.filtered[tabDomain];
|
||||||
if (mainFrame) {
|
if (mainFrame) {
|
||||||
const promptOption = ns.sync.TabGuardPrompt;
|
const promptOption = ns.sync.TabGuardPrompt;
|
||||||
|
|
||||||
|
@ -238,9 +281,9 @@ var TabGuard = (() => {
|
||||||
if (ret.button !== 0) {
|
if (ret.button !== 0) {
|
||||||
return {cancel: true};
|
return {cancel: true};
|
||||||
}
|
}
|
||||||
const groups = ret.option === 0 ? filteredGroups : allowedGroups;
|
const groups = ret.option === 0 ? Groups.filtered : Groups.allowed;
|
||||||
mergeGroups(groups, {tabDomain, otherDomains});
|
mergeGroups(groups, {tabDomain, otherDomains});
|
||||||
return groups === filteredGroups ? filterAuth() : null;
|
return groups === Groups.filtered ? filterAuth() : null;
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,7 +331,7 @@ var TabGuard = (() => {
|
||||||
allow(tabId) {
|
allow(tabId) {
|
||||||
if (!TabGuard.isAnonymizedTab(tabId)) return;
|
if (!TabGuard.isAnonymizedTab(tabId)) return;
|
||||||
const info = this.getAnonymizedTabInfo(tabId);
|
const info = this.getAnonymizedTabInfo(tabId);
|
||||||
mergeGroups(allowedGroups, info);
|
mergeGroups(Groups.allowed, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
if (!isTorBrowser) {
|
if (!isTorBrowser) {
|
||||||
await include("/nscl/service/prefetchCSSResources.js");
|
await include("/nscl/service/prefetchCSSResources.js");
|
||||||
}
|
}
|
||||||
|
await TabGuard.wakening;
|
||||||
await RequestGuard.start();
|
await RequestGuard.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -58,9 +58,12 @@
|
||||||
"/nscl/common/DNS.js",
|
"/nscl/common/DNS.js",
|
||||||
"/nscl/common/AddressMatcherWithDNS.js",
|
"/nscl/common/AddressMatcherWithDNS.js",
|
||||||
"/nscl/common/iputil.js",
|
"/nscl/common/iputil.js",
|
||||||
|
"/nscl/common/SessionCache.js",
|
||||||
"/nscl/service/DocStartInjection.js",
|
"/nscl/service/DocStartInjection.js",
|
||||||
"/nscl/service/LastListener.js",
|
"/nscl/service/LastListener.js",
|
||||||
"/nscl/service/patchWorkers.js",
|
"/nscl/service/patchWorkers.js",
|
||||||
|
"/nscl/service/TabCache.js",
|
||||||
|
"/nscl/service/TabTies.js",
|
||||||
"ui/Prompts.js",
|
"ui/Prompts.js",
|
||||||
"xss/XSS.js",
|
"xss/XSS.js",
|
||||||
"bg/ReportingCSP.js",
|
"bg/ReportingCSP.js",
|
||||||
|
|
2
src/nscl
2
src/nscl
|
@ -1 +1 @@
|
||||||
Subproject commit 3ba8d9a4cb4c57abb2611343cc8641882f5715c2
|
Subproject commit 9705b11ac271b44c70fc086a162326a83c0b2dbe
|
Loading…
Reference in New Issue