Use cookie instead of window.name as a tab-configuration hack.

This commit is contained in:
hackademix 2018-10-13 10:08:37 +02:00
parent e44fce3ebd
commit 808fd652be
4 changed files with 30 additions and 36 deletions

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
{ {
let marker = JSON.stringify(uuid()); let marker = uuid();
let allUrls = ["<all_urls>"]; let allUrls = ["<all_urls>"];
let Scripts = { let Scripts = {
@ -47,7 +47,7 @@
if (typeof perms !== "string") { if (typeof perms !== "string") {
perms = JSON.stringify(perms); perms = JSON.stringify(perms);
} }
return `ns.setup(${perms}, ${marker});` return `ns.setup(${perms}, "${marker}");`
} }
}; };
@ -104,18 +104,17 @@
: []; : [];
var ChildPolicies = { var ChildPolicies = {
async storeTabInfo(tabId, info) { addTabInfoCookie(request, info) {
try { let h = {
let preamble = info ? `${marker} + ${JSON.stringify(JSON.stringify([info]))} + ${marker} + "," + ` : ""; name: "Set-Cookie",
await browser.tabs.executeScript(tabId, { value: `${marker}=${JSON.stringify(info)}`
code: `window.name = ${preamble}window.name.split(${marker} + ",").pop();`, };
allFrames: true, let {responseHeaders} = request;
matchAboutBlank: true, if (responseHeaders.some(({value, name}) => h.value === value && h.name === name)) {
runAt: "document_start", return false;
});
} catch (e) {
error(e);
} }
responseHeaders.push(h);
return true;
}, },
async update(policy, tracing) { async update(policy, tracing) {
if (tracing !== "undefined") Scripts.debug = tracing; if (tracing !== "undefined") Scripts.debug = tracing;
@ -123,7 +122,7 @@
await Scripts.init(); await Scripts.init();
if (!policy.enforced) { if (!policy.enforced) {
await Scripts.register(`ns.setup(null, ${marker});`, allUrls); await Scripts.register(Scripts.buildPerms("null"), allUrls);
return; return;
} }

View File

@ -292,6 +292,7 @@ var RequestGuard = (() => {
async onHeadersReceived(request) { async onHeadersReceived(request) {
// called for main_frame, sub_frame and object // called for main_frame, sub_frame and object
// check for duplicate calls // check for duplicate calls
let headersModified = false;
let pending = pendingRequests.get(request.requestId); let pending = pendingRequests.get(request.requestId);
if (pending) { if (pending) {
if (pending.headersProcessed) { if (pending.headersProcessed) {
@ -319,7 +320,10 @@ var RequestGuard = (() => {
capabilities = perms.capabilities; capabilities = perms.capabilities;
} else { } else {
if (isMainFrame || type === "sub_frame") { if (isMainFrame || type === "sub_frame") {
await Settings.enforceTabRestrictions(tabId); let unrestricted = ns.unrestrictedTabs.has(tabId) && {unrestricted: true};
if (unrestricted) {
headersModified = ChildPolicies.addTabInfoCookie(request, unrestricted);
}
} }
} }
if (isMainFrame && !TabStatus.map.has(tabId)) { if (isMainFrame && !TabStatus.map.has(tabId)) {
@ -331,6 +335,9 @@ var RequestGuard = (() => {
if (header) { if (header) {
pending.cspHeader = header; pending.cspHeader = header;
debug(`CSP blocker on %s:`, url, header.value); debug(`CSP blocker on %s:`, url, header.value);
headersModified = true;
}
if (headersModified) {
return {responseHeaders}; return {responseHeaders};
} }
} catch (e) { } catch (e) {

View File

@ -90,7 +90,6 @@ var Settings = {
if (typeof unrestrictedTab === "boolean") { if (typeof unrestrictedTab === "boolean") {
ns.unrestrictedTabs[unrestrictedTab ? "add" : "delete"](tabId); ns.unrestrictedTabs[unrestrictedTab ? "add" : "delete"](tabId);
this.enforceTabRestrictions(tabId, unrestrictedTab);
} }
if (reloadAffected) { if (reloadAffected) {
browser.tabs.reload(tabId); browser.tabs.reload(tabId);

View File

@ -47,33 +47,22 @@
this.config.permissions = permissions; this.config.permissions = permissions;
// ugly hack: since now we use registerContentScript instead of the // ugly hack: since now we use registerContentScript instead of the
// filterRequest dynamic script injection hack, we use window.name // filterRequest dynamic script injection hack, we use a session cookie
// to store per-tab information. We don't want web content to // to store per-tab information, erasing it as soon as we see it
// mess with it, though, so we wrap it around auto-hiding accessors // (before any content can access it)
if (this.config.MARKER = MARKER) { if (this.config.MARKER = MARKER) {
let splitter = `${MARKER},`; let cookieRx = new RegExp(`(?:^|;\\s*)${MARKER}=([^;]*)`);
this.getWindowName = () => window.name.split(splitter).pop(); let match = document.cookie.match(cookieRx);
if (match) {
let tabInfoRx = new RegExp(`^${MARKER}\\[([^]*?)\\]${MARKER},`); // delete cookie NOW
document.cookie = `${MARKER}=;expires=${new Date(Date.now() - 31536000000).toGMTString()}`;
let tabInfoMatch = window.name.match(tabInfoRx);
if (tabInfoMatch) {
try { try {
this.config.tabInfo = JSON.parse(tabInfoMatch[1]); this.config.tabInfo = JSON.parse(decodeURIComponent(match[1]));
} catch (e) { } catch (e) {
error(e); error(e);
} }
} }
Reflect.defineProperty(window.wrappedJSObject, "name", {
get: exportFunction(() => this.getWindowName(), window.wrappedJSObject),
set: exportFunction(value => {
let tabInfoMatch = window.name.match(tabInfoRx);
window.name = tabInfoMatch ? `${tabInfoMatch[0]}${value}` : value;
return value;
}, window.wrappedJSObject)
});
} }
if (!this.config.permissions || this.config.tabInfo.unrestricted) { if (!this.config.permissions || this.config.tabInfo.unrestricted) {
debug("%s is loading unrestricted by user's choice (%o).", document.URL, this.config); debug("%s is loading unrestricted by user's choice (%o).", document.URL, this.config);