More efficient window.name persistence for tab-scoped permissions.

This commit is contained in:
hackademix 2018-09-08 23:09:39 +02:00
parent b60cbbd49e
commit 4f7d8579af
4 changed files with 44 additions and 32 deletions

View File

@ -102,7 +102,7 @@
let preamble = info ? `${marker} + ${JSON.stringify(JSON.stringify([info]))} + ${marker} + "," + ` : ""; let preamble = info ? `${marker} + ${JSON.stringify(JSON.stringify([info]))} + ${marker} + "," + ` : "";
await browser.tabs.executeScript(tabId, { await browser.tabs.executeScript(tabId, {
code: `window.name = ${preamble}window.name.split(${marker} + ",").pop();`, code: `window.name = ${preamble}window.name.split(${marker} + ",").pop();`,
allFrames: false, allFrames: true,
matchAboutBlank: true, matchAboutBlank: true,
runAt: "document_start", runAt: "document_start",
}); });

View File

@ -317,6 +317,10 @@ var RequestGuard = (() => {
await ChildPolicies.update(policy); await ChildPolicies.update(policy);
} }
capabilities = perms.capabilities; capabilities = perms.capabilities;
} else {
if (!isMainFrame && type === "sub_frame") {
await Settings.enforceTabRestrictions(tabId);
}
} }
if (isMainFrame && !TabStatus.map.has(tabId)) { if (isMainFrame && !TabStatus.map.has(tabId)) {
debug("No TabStatus data yet for noscriptFrame", tabId); debug("No TabStatus data yet for noscriptFrame", tabId);

View File

@ -90,7 +90,7 @@ var Settings = {
if (typeof unrestrictedTab === "boolean") { if (typeof unrestrictedTab === "boolean") {
ns.unrestrictedTabs[unrestrictedTab ? "add" : "delete"](tabId); ns.unrestrictedTabs[unrestrictedTab ? "add" : "delete"](tabId);
ChildPolicies.storeTabInfo(tabId, unrestrictedTab && {unrestricted: true}); this.enforceTabRestrictions(tabId, unrestrictedTab);
} }
if (reloadAffected) { if (reloadAffected) {
browser.tabs.reload(tabId); browser.tabs.reload(tabId);
@ -123,4 +123,8 @@ var Settings = {
}, null, 2); }, null, 2);
}, },
async enforceTabRestrictions(tabId, unrestricted = ns.unrestrictedTabs.has(tabId)) {
await ChildPolicies.storeTabInfo(tabId, unrestricted && {unrestricted: true});
return unrestricted;
}
} }

View File

@ -38,33 +38,40 @@
if(!this.config.CURRENT) this.config.CURRENT = DEFAULT; if(!this.config.CURRENT) this.config.CURRENT = DEFAULT;
// 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 top.name // filterRequest dynamic script injection hack, we use window.name
// to store per-tab information. We don't want web content to // to store per-tab information. We don't want web content to
// mess with it, though, so we wrap it around auto-hiding accessors // mess with it, though, so we wrap it around auto-hiding accessors
this.config.MARKER = MARKER;
let eraseTabInfoRx = new RegExp(`[^]*${MARKER},?`);
if (eraseTabInfoRx.test(top.name)) {
let _name = top.name;
let tabInfoRx = new RegExp(`^${MARKER}\\[([^]*?)\\]${MARKER},`);
if (top === window) { // wrap to hide
Reflect.defineProperty(top.wrappedJSObject, "name", {
get: exportFunction(() => top.name.replace(eraseTabInfoRx, ""), top.wrappedJSObject),
set: exportFunction(value => {
let preamble = top.name.match(tabInfoRx);
top.name = `${preamble && preamble[0] || ""}${value}`;
return value;
}, top.wrappedJSObject)
});
}
let tabInfoMatch = _name.match(tabInfoRx);
if (tabInfoMatch) try {
this.config.tabInfo = JSON.parse(tabInfoMatch[1]);
} catch (e) {
error(e);
}
}
if (this.config.MARKER = MARKER) {
let tabInfoRx = new RegExp(`^${MARKER}\\[([^]*?)\\]${MARKER},`);
let name = window.name;
try {
name = top.name;
} catch(e) {
// won't work cross-origin
}
let tabInfoMatch = name.match(tabInfoRx);
if (tabInfoMatch) {
try {
this.config.tabInfo = JSON.parse(tabInfoMatch[1]);
} catch (e) {
error(e);
}
}
let splitter = `${MARKER},`;
this.getWindowName = () => window.name.split(splitter).pop();
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.DEFAULT || this.config.tabInfo.unrestricted) { if (!this.config.DEFAULT || this.config.tabInfo.unrestricted) {
debug("%s is loading unrestricted by user's choice (%o).", document.URL, this.config);
this.allows = () => true; this.allows = () => true;
this.capabilities = Object.assign( this.capabilities = Object.assign(
new Set(["script"]), { has() { return true; } }); new Set(["script"]), { has() { return true; } });
@ -84,10 +91,7 @@
}, },
getWindowName() { getWindowName() {
let marker = this.config.MARKER; return window.name;
return (top === window && marker) ?
window.name.split(`${marker},`).pop()
: window.name;
} }
}; };