summaryrefslogtreecommitdiff
path: root/src/bg/ChildPolicies.js
diff options
context:
space:
mode:
authorhackademix2018-08-15 16:41:55 +0200
committerhackademix2018-08-16 23:43:36 +0200
commit57d883d63e9b8232e275dac7eec24f84c040dd24 (patch)
treea4a9f05f0744ccef23e31643f80c400abe0dab37 /src/bg/ChildPolicies.js
parent2c75eedadddd8bda0522cddaf119e1e5c621c7c2 (diff)
downloadnoscript-57d883d63e9b8232e275dac7eec24f84c040dd24.tar.gz
noscript-57d883d63e9b8232e275dac7eec24f84c040dd24.tar.xz
noscript-57d883d63e9b8232e275dac7eec24f84c040dd24.zip
Policy serialization using the contentScripts API.
Diffstat (limited to 'src/bg/ChildPolicies.js')
-rw-r--r--src/bg/ChildPolicies.js111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/bg/ChildPolicies.js b/src/bg/ChildPolicies.js
new file mode 100644
index 0000000..fd790c9
--- /dev/null
+++ b/src/bg/ChildPolicies.js
@@ -0,0 +1,111 @@
+"use script";
+{
+ let Scripts = {
+ references: new Set(),
+ opts: {
+ js: [{}],
+ allFrames: true,
+ matchAboutBlank: true,
+ runAt: "document_start"
+ },
+ forget() {
+ for (let script of [...this.references]) {
+ script.unregister();
+ this.references.delete(script);
+ }
+ },
+ async register(code, matches, excludeMatches) {
+ debug("Registering child policy.", code, matches, excludeMatches);
+ if (!matches.length) return;
+ try {
+ this.opts.js[0].code = code;
+ this.opts.matches = matches;
+ if (excludeMatches && excludeMatches.length) {
+ this.opts.excludeMatches = excludeMatches;
+ } else {
+ delete this.opts.excludeMatches;
+ }
+ this.references.add(await browser.contentScripts.register(this.opts));
+ } catch (e) {
+ error(e);
+ }
+ }
+ };
+
+ let flatten = arr => arr.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
+
+ let protocolRx = /^(https?):/i;
+ let pathRx = /[^:/]\//;
+ let portRx = /:\d+(?=\/|$)/;
+ let validMatchPatternRx = /^(?:https?|\*):\/\/(?:\*\.)?(?:[\w\u0100-\uf000][\w\u0100-\uf000.-]*)?[\w\u0100-\uf000]\/(\*|[^*]*)$/;
+
+ let siteKey2MatchPattern = site => {
+ let hasProtocol = site.match(protocolRx);
+ let protocol = hasProtocol ? ''
+ : Sites.isSecureDomainKey(site) ? "https://" : "*://";
+ let hostname = Sites.toggleSecureDomainKey(site, false)
+ .replace(portRx, '');
+ if (!hasProtocol) hostname = `*.${hostname}`;
+ let path = pathRx.test(hostname) ? "" : "/*";
+ let mp = `${protocol}${hostname}${path}`;
+ return validMatchPatternRx.test(mp) && (path ? mp : [mp, `${mp}?*`, `${mp}#*`]);
+ };
+
+ let siteKeys2MatchPatterns = keys => keys && flatten(keys.map(siteKey2MatchPattern)).filter(p => !!p) || [];
+
+ var ChildPolicies = {
+ async update(policy) {
+ let serialized = policy.dry ? policy.dry(true) : policy;
+ let permsMap = new Map();
+ let trusted = JSON.stringify(serialized.TRUSTED);
+ let untrusted = JSON.stringify(serialized.UNTRUSTED);
+ let presets = {
+ trusted,
+ untrusted,
+ temp: trusted
+ };
+ // map presets to site keys
+ for (let [container, perms] of Object.entries(presets)) {
+ let newKeys = serialized.sites[container];
+ if (!(newKeys && newKeys.length)) continue;
+ let keys = permsMap.get(perms);
+ if (keys) {
+ newKeys = keys.concat(newKeys);
+ }
+ permsMap.set(perms, newKeys);
+ }
+ // map custom permissions to site keys
+ for (let [key, perms] of Object.entries(serialized.sites.custom)) {
+ let permsKey = JSON.stringify(perms);
+ let keys = permsMap.get(permsKey);
+ if (keys) {
+ keys.push(key);
+ } else {
+ permsMap.set(permsKey, [key]);
+ }
+ }
+
+ // compute exclusions
+ let permsMapEntries = [...permsMap];
+ let excludeMap = new Map();
+ for (let [perms, keys] of permsMapEntries) {
+ excludeMap.set(perms, siteKeys2MatchPatterns(flatten(
+ permsMapEntries.filter(([other]) => other !== perms)
+ .map(([otherPerms, otherKeys]) => otherKeys))
+ .filter(k => k && k.includes("/"))
+ ));
+ }
+
+ Scripts.forget();
+ // register new content scripts
+ for (let [perms, keys] of [...permsMap]) {
+ await Scripts.register(`ns.perms.CURRENT = ${perms};`, siteKeys2MatchPatterns(keys), excludeMap.get(perms));
+ }
+ await Scripts.register(
+ `ns.perms.DEFAULT = ${JSON.stringify(serialized.DEFAULT)};
+ if(!ns.perms.CURRENT) ns.perms.CURRENT = ns.perms.DEFAULT;
+ ns.fire("perms");`,
+ ["<all_urls>"]);
+ }
+ }
+}