From 57e4ed2b06d15747b20737bad14bcdd2d73fd8a6 Mon Sep 17 00:00:00 2001 From: jahoti Date: Wed, 21 Jul 2021 00:00:00 +0000 Subject: Remove unnecessary imports of url_item and add a CSP header-parsing function The parsing function isn't used yet; however, it will eventually be as a less destructive alternative to handling headers as indivisible units. --- background/policy_injector.js | 1 - 1 file changed, 1 deletion(-) (limited to 'background/policy_injector.js') diff --git a/background/policy_injector.js b/background/policy_injector.js index 01da094..9a994f8 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -16,7 +16,6 @@ * IMPORT gen_unique * IMPORT gen_nonce * IMPORT is_privileged_url - * IMPORT url_item * IMPORT url_extract_target * IMPORT sign_policy * IMPORT get_query_best -- cgit v1.2.3 From fba4820bec6714115ef03bd4bdfd714ba485ac2c Mon Sep 17 00:00:00 2001 From: jahoti Date: Wed, 21 Jul 2021 00:00:00 +0000 Subject: [UNTESTED- will test] Use more nuanced CSP filtering CSP headers are now parsed and processed, rather than treated as simple units. This allows us to ensure policies delivered as HTTP headers do not interfere with our script filtering, as well as to preserve useful protections while removing the ones that could be problematic. Additionally, prefetching should now be blocked on pages where native scripts aren't allowed, and all reporting of CSP violations has been stripped (is this appropriate?). --- background/policy_injector.js | 72 +++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 19 deletions(-) (limited to 'background/policy_injector.js') diff --git a/background/policy_injector.js b/background/policy_injector.js index 9a994f8..a67b4e3 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -12,14 +12,13 @@ * IMPORT get_storage * IMPORT browser * IMPORT is_chrome - * IMPORT is_mozilla * IMPORT gen_unique * IMPORT gen_nonce * IMPORT is_privileged_url * IMPORT url_extract_target * IMPORT sign_policy * IMPORT get_query_best - * IMPORT csp_rule + * IMPORT parse_csp * IMPORTS_END */ @@ -32,11 +31,19 @@ const csp_header_names = { "x-content-security-policy" : true }; +const unwanted_csp_directives = { + "report-to" : true, + "report-uri" : true, + "script-src" : true, + "script-src-elem" : true, + "prefetch-src": true +}; + const header_name = "content-security-policy"; -function is_csp_header(header) +function not_csp_header(header) { - return !!csp_header_names[header.name.toLowerCase()]; + return !csp_header_names[header.name.toLowerCase()]; } function url_inject(details) @@ -82,21 +89,48 @@ function headers_inject(details) if (!targets.current) return {cancel: true}; - const rule = csp_rule(targets.policy.nonce); - var headers = details.responseHeaders; - - /* - * Chrome doesn't have the buggy behavior of caching headers - * we injected. Firefox does and we have to remove it there. - */ - if (!targets.policy.allow || is_mozilla) - headers = headers.filter(h => !is_csp_header(h)); - - if (!targets.policy.allow) { - headers.push({ - name : header_name, - value : rule - }); + const headers = []; + for (let header of details.responseHeaders) { + if (not_csp_header(header)) { + /* Retain all non-snitching headers */ + if (header.name.toLowerCase() !== + 'content-security-policy-report-only') + headers.push(header); + + continue; + } + + const csp = parse_csp(header.value); + const rule = `'nonce-${targets.policy.nonce}'` + + /* TODO: confirm deleting non-existent things is OK everywhere */ + /* No snitching or prefetching/rendering */ + delete csp['report-to']; + delete csp['report-uri']; + + if (!target.policy.allow) { + delete csp['script-src']; + delete csp['script-src-elem']; + csp['script-src-attr'] = ["'none'"]; + csp['prefetch-src'] = ["'none'"]; + } + + if ('script-src' in csp) + csp['script-src'].push(rule); + else + csp['script-src'] = rule; + + if ('script-src-elem' in csp) + csp['script-src-elem'].push(rule); + else + csp['script-src-elem'] = rule; + + /* TODO: is this safe */ + let new_policy = Object.entries(csp).map( + i => i[0] + ' ' + i[1].join(' ') + ';' + ); + + headers.push({name: header.name, value: new_policy.join('')}); } return {responseHeaders: headers}; -- cgit v1.2.3 From e402e0363cd55f7f849c20c1acd96de548ebc9a6 Mon Sep 17 00:00:00 2001 From: jahoti Date: Thu, 22 Jul 2021 00:00:00 +0000 Subject: Fix some bugs in the refined CSP handling --- background/policy_injector.js | 6 +++--- common/misc.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'background/policy_injector.js') diff --git a/background/policy_injector.js b/background/policy_injector.js index a67b4e3..90c65bd 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -108,7 +108,7 @@ function headers_inject(details) delete csp['report-to']; delete csp['report-uri']; - if (!target.policy.allow) { + if (!targets.policy.allow) { delete csp['script-src']; delete csp['script-src-elem']; csp['script-src-attr'] = ["'none'"]; @@ -118,12 +118,12 @@ function headers_inject(details) if ('script-src' in csp) csp['script-src'].push(rule); else - csp['script-src'] = rule; + csp['script-src'] = [rule]; if ('script-src-elem' in csp) csp['script-src-elem'].push(rule); else - csp['script-src-elem'] = rule; + csp['script-src-elem'] = [rule]; /* TODO: is this safe */ let new_policy = Object.entries(csp).map( diff --git a/common/misc.js b/common/misc.js index 6af2327..0d8466e 100644 --- a/common/misc.js +++ b/common/misc.js @@ -159,7 +159,7 @@ function parse_csp(csp) { let directive, directive_array; let directives = {}; for (directive of csp.split(';')) { - directive = directive.trim; + directive = directive.trim(); if (directive === '') continue; -- cgit v1.2.3 From 97b8e30fadf0f1e1e0aeb9078ac333026d735270 Mon Sep 17 00:00:00 2001 From: jahoti Date: Sun, 25 Jul 2021 00:00:00 +0000 Subject: Squash more CSP-filtering bugs On Firefox, original CSP headers are now smuggled (signed) in an x-orig-csp header to prevent re-processing issues with caching. Additionally, a default header is added for non-whitelisted domains in case there are no existing headers we can attach to. --- background/policy_injector.js | 133 +++++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 35 deletions(-) (limited to 'background/policy_injector.js') diff --git a/background/policy_injector.js b/background/policy_injector.js index 90c65bd..f58fb71 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -12,6 +12,7 @@ * IMPORT get_storage * IMPORT browser * IMPORT is_chrome + * IMPORT is_mozilla * IMPORT gen_unique * IMPORT gen_nonce * IMPORT is_privileged_url @@ -39,7 +40,7 @@ const unwanted_csp_directives = { "prefetch-src": true }; -const header_name = "content-security-policy"; +const report_only = "content-security-policy-report-only"; function not_csp_header(header) { @@ -82,6 +83,38 @@ function url_inject(details) }; } +function process_csp_header(header, rule, block) +{ + const csp = parse_csp(header.value); + + /* No snitching */ + delete csp['report-to']; + delete csp['report-uri']; + + if (block) { + delete csp['script-src']; + delete csp['script-src-elem']; + csp['script-src-attr'] = ["'none'"]; + csp['prefetch-src'] = ["'none'"]; + } + + if ('script-src' in csp) + csp['script-src'].push(rule); + else + csp['script-src'] = [rule]; + + if ('script-src-elem' in csp) + csp['script-src-elem'].push(rule); + else + csp['script-src-elem'] = [rule]; + + const new_policy = Object.entries(csp).map( + i => i[0] + ' ' + i[1].join(' ') + ';' + ); + + return {name: header.name, value: new_policy.join('')} +} + function headers_inject(details) { const targets = url_extract_target(details.url); @@ -89,48 +122,78 @@ function headers_inject(details) if (!targets.current) return {cancel: true}; - const headers = []; + let orig_csp_headers = is_chrome ? null : []; + let headers = []; + let csp_headers = is_chrome ? headers : []; + + const rule = `'nonce-${targets.policy.nonce}'`; + const block = !targets.policy.allow; + for (let header of details.responseHeaders) { if (not_csp_header(header)) { /* Retain all non-snitching headers */ - if (header.name.toLowerCase() !== - 'content-security-policy-report-only') + if (header.name.toLowerCase() !== report_only) { headers.push(header); + + /* If these are the original CSP headers, use them instead */ + /* Test based on url_extract_target() in misc.js */ + if (is_mozilla && header.name === "x-orig-csp") { + let index = header.value.indexOf('%5B'); + if (index === -1) + continue; + + let sig = header.value.substring(0, index); + let data = header.value.substring(index); + if (sig !== sign_policy(data, 0)) + continue; + + /* Confirmed- it's the originals, smuggled in! */ + try { + data = JSON.parse(decodeURIComponent(data)); + } catch (e) { + /* This should not be reached - + it's our self-produced valid JSON. */ + console.log("Unexpected internal error - invalid JSON smuggled!", e); + } + + orig_csp_headers = csp_headers = null; + for (let header of data) + headers.push(process_csp_header(header, rule, block)); + } + } continue; } - - const csp = parse_csp(header.value); - const rule = `'nonce-${targets.policy.nonce}'` - - /* TODO: confirm deleting non-existent things is OK everywhere */ - /* No snitching or prefetching/rendering */ - delete csp['report-to']; - delete csp['report-uri']; - - if (!targets.policy.allow) { - delete csp['script-src']; - delete csp['script-src-elem']; - csp['script-src-attr'] = ["'none'"]; - csp['prefetch-src'] = ["'none'"]; - } - - if ('script-src' in csp) - csp['script-src'].push(rule); - else - csp['script-src'] = [rule]; - - if ('script-src-elem' in csp) - csp['script-src-elem'].push(rule); - else - csp['script-src-elem'] = [rule]; - - /* TODO: is this safe */ - let new_policy = Object.entries(csp).map( - i => i[0] + ' ' + i[1].join(' ') + ';' - ); + if (is_mozilla && !orig_csp_headers) + continue; - headers.push({name: header.name, value: new_policy.join('')}); + csp_headers.push(process_csp_header(header, rule, block)); + if (is_mozilla) + orig_csp_headers.push(header); + } + + if (orig_csp_headers) { + /** Smuggle in the original CSP headers for future use. + * These are signed with a time of 0, as it's not clear there + * is a limit on how long Firefox might retain these headers in + * the cache. + */ + orig_csp_headers = encodeURIComponent(JSON.stringify(orig_csp_headers)); + headers.push({ + name: "x-orig-csp", + value: sign_policy(orig_csp_headers, 0) + orig_csp_headers + }); + + headers = headers.concat(csp_headers); + } + + /* To ensure there is a CSP header if required */ + if (block) { + headers.push({ + name: "content-security-policy", + value: `script-src ${rule}; script-src-elem ${rule}; ` + + "script-src-attr 'none'; prefetch-src 'none';" + }); } return {responseHeaders: headers}; -- cgit v1.2.3 From 5fcc980828047e966c24fde8a80e7f819a457e36 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Mon, 26 Jul 2021 12:10:13 +0200 Subject: code maintenance --- background/policy_injector.js | 58 ++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 31 deletions(-) (limited to 'background/policy_injector.js') diff --git a/background/policy_injector.js b/background/policy_injector.js index f58fb71..386cf22 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -26,27 +26,23 @@ var storage; var query_best; -const csp_header_names = { - "content-security-policy" : true, - "x-webkit-csp" : true, - "x-content-security-policy" : true -}; - -const unwanted_csp_directives = { - "report-to" : true, - "report-uri" : true, - "script-src" : true, - "script-src-elem" : true, - "prefetch-src": true -}; +const csp_header_names = new Set([ + "content-security-policy", + "x-webkit-csp", + "x-content-security-policy" +]); + +/* TODO: variable no longer in use; remove if not needed */ +const unwanted_csp_directives = new Set([ + "report-to", + "report-uri", + "script-src", + "script-src-elem", + "prefetch-src" +]); const report_only = "content-security-policy-report-only"; -function not_csp_header(header) -{ - return !csp_header_names[header.name.toLowerCase()]; -} - function url_inject(details) { if (is_privileged_url(details.url)) @@ -86,18 +82,18 @@ function url_inject(details) function process_csp_header(header, rule, block) { const csp = parse_csp(header.value); - + /* No snitching */ delete csp['report-to']; delete csp['report-uri']; - + if (block) { delete csp['script-src']; delete csp['script-src-elem']; csp['script-src-attr'] = ["'none'"]; csp['prefetch-src'] = ["'none'"]; } - + if ('script-src' in csp) csp['script-src'].push(rule); else @@ -107,12 +103,12 @@ function process_csp_header(header, rule, block) csp['script-src-elem'].push(rule); else csp['script-src-elem'] = [rule]; - + const new_policy = Object.entries(csp).map( - i => i[0] + ' ' + i[1].join(' ') + ';' + i => `${i[0]} ${i[1].join(' ')};` ); - - return {name: header.name, value: new_policy.join('')} + + return {name: header.name, value: new_policy.join('')}; } function headers_inject(details) @@ -128,13 +124,13 @@ function headers_inject(details) const rule = `'nonce-${targets.policy.nonce}'`; const block = !targets.policy.allow; - - for (let header of details.responseHeaders) { - if (not_csp_header(header)) { + + for (const header of details.responseHeaders) { + if (!csp_header_names.has(header)) { /* Retain all non-snitching headers */ if (header.name.toLowerCase() !== report_only) { headers.push(header); - + /* If these are the original CSP headers, use them instead */ /* Test based on url_extract_target() in misc.js */ if (is_mozilla && header.name === "x-orig-csp") { @@ -157,7 +153,7 @@ function headers_inject(details) } orig_csp_headers = csp_headers = null; - for (let header of data) + for (const header of data) headers.push(process_csp_header(header, rule, block)); } } @@ -166,7 +162,7 @@ function headers_inject(details) } if (is_mozilla && !orig_csp_headers) continue; - + csp_headers.push(process_csp_header(header, rule, block)); if (is_mozilla) orig_csp_headers.push(header); -- cgit v1.2.3 From 25817b68c03b25c9b4fcaba2b96ab65f2edfd63c Mon Sep 17 00:00:00 2001 From: jahoti Date: Wed, 28 Jul 2021 00:00:00 +0000 Subject: Rationalize CSP violation report blocking. Report blocking now applies iff scripts are blocked. --- background/policy_injector.js | 76 +++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 39 deletions(-) (limited to 'background/policy_injector.js') diff --git a/background/policy_injector.js b/background/policy_injector.js index 386cf22..f573d48 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -83,13 +83,15 @@ function process_csp_header(header, rule, block) { const csp = parse_csp(header.value); - /* No snitching */ - delete csp['report-to']; - delete csp['report-uri']; if (block) { + /* No snitching */ + delete csp['report-to']; + delete csp['report-uri']; + delete csp['script-src']; delete csp['script-src-elem']; + csp['script-src-attr'] = ["'none'"]; csp['prefetch-src'] = ["'none'"]; } @@ -127,45 +129,41 @@ function headers_inject(details) for (const header of details.responseHeaders) { if (!csp_header_names.has(header)) { - /* Retain all non-snitching headers */ - if (header.name.toLowerCase() !== report_only) { - headers.push(header); - - /* If these are the original CSP headers, use them instead */ - /* Test based on url_extract_target() in misc.js */ - if (is_mozilla && header.name === "x-orig-csp") { - let index = header.value.indexOf('%5B'); - if (index === -1) - continue; - - let sig = header.value.substring(0, index); - let data = header.value.substring(index); - if (sig !== sign_policy(data, 0)) - continue; - - /* Confirmed- it's the originals, smuggled in! */ - try { - data = JSON.parse(decodeURIComponent(data)); - } catch (e) { - /* This should not be reached - - it's our self-produced valid JSON. */ - console.log("Unexpected internal error - invalid JSON smuggled!", e); - } - - orig_csp_headers = csp_headers = null; - for (const header of data) - headers.push(process_csp_header(header, rule, block)); + /* Remove headers that only snitch on us */ + if (header.name.toLowerCase() === report_only && block) + continue; + headers.push(header); + + /* If these are the original CSP headers, use them instead */ + /* Test based on url_extract_target() in misc.js */ + if (is_mozilla && header.name === "x-orig-csp") { + let index = header.value.indexOf('%5B'); + if (index === -1) + continue; + + let sig = header.value.substring(0, index); + let data = header.value.substring(index); + if (sig !== sign_policy(data, 0)) + continue; + + /* Confirmed- it's the originals, smuggled in! */ + try { + data = JSON.parse(decodeURIComponent(data)); + } catch (e) { + /* This should not be reached - + it's our self-produced valid JSON. */ + console.log("Unexpected internal error - invalid JSON smuggled!", e); } - } - continue; + orig_csp_headers = csp_headers = null; + for (const header of data) + headers.push(process_csp_header(header, rule, block)); + } + } else if (is_chrome || !orig_csp_headers) { + csp_headers.push(process_csp_header(header, rule, block)); + if (is_mozilla) + orig_csp_headers.push(header); } - if (is_mozilla && !orig_csp_headers) - continue; - - csp_headers.push(process_csp_header(header, rule, block)); - if (is_mozilla) - orig_csp_headers.push(header); } if (orig_csp_headers) { -- cgit v1.2.3 From 5b419aedd564e6506aa2fc8bddcaa5d601888f17 Mon Sep 17 00:00:00 2001 From: jahoti Date: Mon, 2 Aug 2021 00:00:00 +0000 Subject: [UNTESTED- will test] Add filtering for http-equiv CSP headers --- background/policy_injector.js | 40 +++------------------------------------- common/misc.js | 36 +++++++++++++++++++++++++++++++++++- content/main.js | 27 +++++++++++++++++++-------- 3 files changed, 57 insertions(+), 46 deletions(-) (limited to 'background/policy_injector.js') diff --git a/background/policy_injector.js b/background/policy_injector.js index f573d48..80a0e3b 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -19,7 +19,7 @@ * IMPORT url_extract_target * IMPORT sign_policy * IMPORT get_query_best - * IMPORT parse_csp + * IMPORT sanitize_csp_header * IMPORTS_END */ @@ -79,40 +79,6 @@ function url_inject(details) }; } -function process_csp_header(header, rule, block) -{ - const csp = parse_csp(header.value); - - - if (block) { - /* No snitching */ - delete csp['report-to']; - delete csp['report-uri']; - - delete csp['script-src']; - delete csp['script-src-elem']; - - csp['script-src-attr'] = ["'none'"]; - csp['prefetch-src'] = ["'none'"]; - } - - if ('script-src' in csp) - csp['script-src'].push(rule); - else - csp['script-src'] = [rule]; - - if ('script-src-elem' in csp) - csp['script-src-elem'].push(rule); - else - csp['script-src-elem'] = [rule]; - - const new_policy = Object.entries(csp).map( - i => `${i[0]} ${i[1].join(' ')};` - ); - - return {name: header.name, value: new_policy.join('')}; -} - function headers_inject(details) { const targets = url_extract_target(details.url); @@ -157,10 +123,10 @@ function headers_inject(details) orig_csp_headers = csp_headers = null; for (const header of data) - headers.push(process_csp_header(header, rule, block)); + headers.push(sanitize_csp_header(header, rule, block)); } } else if (is_chrome || !orig_csp_headers) { - csp_headers.push(process_csp_header(header, rule, block)); + csp_headers.push(sanitize_csp_header(header, rule, block)); if (is_mozilla) orig_csp_headers.push(header); } diff --git a/common/misc.js b/common/misc.js index 0d8466e..d046b65 100644 --- a/common/misc.js +++ b/common/misc.js @@ -173,6 +173,40 @@ function parse_csp(csp) { return directives; } +/* Make CSP headers do our bidding, not interfere */ +function sanitize_csp_header(header, rule, block) +{ + const csp = parse_csp(header.value); + + if (block) { + /* No snitching */ + delete csp['report-to']; + delete csp['report-uri']; + + delete csp['script-src']; + delete csp['script-src-elem']; + + csp['script-src-attr'] = ["'none'"]; + csp['prefetch-src'] = ["'none'"]; + } + + if ('script-src' in csp) + csp['script-src'].push(rule); + else + csp['script-src'] = [rule]; + + if ('script-src-elem' in csp) + csp['script-src-elem'].push(rule); + else + csp['script-src-elem'] = [rule]; + + const new_policy = Object.entries(csp).map( + i => `${i[0]} ${i[1].join(' ')};` + ); + + return {name: header.name, value: new_policy.join('')}; +} + /* * EXPORTS_START * EXPORT gen_nonce @@ -184,6 +218,6 @@ function parse_csp(csp) { * EXPORT nice_name * EXPORT open_in_settings * EXPORT is_privileged_url - * EXPORT parse_csp + * EXPORT sanitize_csp_header * EXPORTS_END */ diff --git a/content/main.js b/content/main.js index 9ed557c..5edb8a6 100644 --- a/content/main.js +++ b/content/main.js @@ -19,6 +19,7 @@ * IMPORT is_chrome * IMPORT is_mozilla * IMPORT start_activity_info_server + * IMPORT sanitize_csp_header * IMPORTS_END */ @@ -65,6 +66,17 @@ function block_node(node) block_script(node); return; } + + else if (node.tagName === 'META' && + node.getAttribute('http-equiv') === 'content-security-policy') { + + node.content = sanitize_csp_header( + {value: node.content}, + `'nonce-${nonce}'`, + !policy.allow + ).value; + return; + } sanitize_attributes(node); @@ -114,14 +126,13 @@ if (!is_privileged_url(document.URL)) { if (!policy.allow) { block_nodes_recursively(document.documentElement); - if (is_chrome) { - var observer = new MutationObserver(handle_mutation); - observer.observe(document.documentElement, { - attributes: true, - childList: true, - subtree: true - }); - } + /* Now needed on Mozilla as well to sanitize CSP header */ + var observer = new MutationObserver(handle_mutation); + observer.observe(document.documentElement, { + attributes: true, + childList: true, + subtree: true + }); if (is_mozilla) addEventListener('beforescriptexecute', mozilla_suppress_scripts, true); -- cgit v1.2.3 From 5957fbeeb47bb2c519d34ae4d2eada2433dd1e09 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Wed, 4 Aug 2021 22:01:01 +0200 Subject: make settings_query.js use storage object passed as an argument --- background/page_actions_server.js | 6 ++-- background/page_info_server.js | 6 ++-- background/policy_injector.js | 6 ++-- background/settings_query.js | 65 --------------------------------------- common/settings_query.js | 52 +++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 77 deletions(-) delete mode 100644 background/settings_query.js create mode 100644 common/settings_query.js (limited to 'background/policy_injector.js') diff --git a/background/page_actions_server.js b/background/page_actions_server.js index a7a44c1..58a0073 100644 --- a/background/page_actions_server.js +++ b/background/page_actions_server.js @@ -13,18 +13,17 @@ * IMPORT browser * IMPORT listen_for_connection * IMPORT sha256 - * IMPORT get_query_best + * IMPORT query_best * IMPORT make_ajax_request * IMPORTS_END */ var storage; -var query_best; var handler; function send_actions(url, port) { - const [pattern, settings] = query_best(url); + const [pattern, settings] = query_best(storage, url); const repos = storage.get_all(TYPE_PREFIX.REPO); port.postMessage(["settings", [pattern, settings, repos]]); @@ -126,7 +125,6 @@ function new_connection(port) async function start_page_actions_server() { storage = await get_storage(); - query_best = await get_query_best(); listen_for_connection(CONNECTION_TYPE.PAGE_ACTIONS, new_connection); } diff --git a/background/page_info_server.js b/background/page_info_server.js index 6f02750..e915011 100644 --- a/background/page_info_server.js +++ b/background/page_info_server.js @@ -10,7 +10,7 @@ * IMPORTS_START * IMPORT listen_for_connection * IMPORT get_storage - * IMPORT get_query_all + * IMPORT query_all * IMPORT TYPE_PREFIX * IMPORT CONNECTION_TYPE * IMPORT url_matches @@ -18,7 +18,6 @@ */ var storage; -var query_all; function handle_change(connection_data, change) { @@ -37,7 +36,7 @@ async function handle_subscription(connection_data, message) } connection_data.subscribed.add(url); - connection_data.port.postMessage(["new_url", query_all(url)]); + connection_data.port.postMessage(["new_url", query_all(storage, url)]); } function new_connection(port) @@ -62,7 +61,6 @@ function new_connection(port) async function start_page_info_server() { storage = await get_storage(); - query_all = await get_query_all(); listen_for_connection(CONNECTION_TYPE.PAGE_INFO, new_connection); } diff --git a/background/policy_injector.js b/background/policy_injector.js index 01da094..b3d85e8 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -19,13 +19,12 @@ * IMPORT url_item * IMPORT url_extract_target * IMPORT sign_policy - * IMPORT get_query_best + * IMPORT query_best * IMPORT csp_rule * IMPORTS_END */ var storage; -var query_best; const csp_header_names = { "content-security-policy" : true, @@ -53,7 +52,7 @@ function url_inject(details) if (targets.policy) targets.target = ""; - let [pattern, settings] = query_best(targets.base_url); + let [pattern, settings] = query_best(storage, targets.base_url); /* Defaults */ if (!pattern) settings = {}; @@ -106,7 +105,6 @@ function headers_inject(details) async function start_policy_injector() { storage = await get_storage(); - query_best = await get_query_best(); let extra_opts = ["blocking", "responseHeaders"]; if (is_chrome) diff --git a/background/settings_query.js b/background/settings_query.js deleted file mode 100644 index d0d9511..0000000 --- a/background/settings_query.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Hachette querying page settings with regard to wildcard records - * - * Copyright (C) 2021 Wojtek Kosior - * Redistribution terms are gathered in the `copyright' file. - */ - -/* - * IMPORTS_START - * IMPORT make_once - * IMPORT get_storage - * IMPORT TYPE_PREFIX - * IMPORT for_each_possible_pattern - * IMPORTS_END - */ - -var storage; - -async function init(fun) -{ - storage = await get_storage(); - - return fun; -} - -function check_pattern(pattern, multiple, matched) -{ - const settings = storage.get(TYPE_PREFIX.PAGE, pattern); - - if (settings === undefined) - return; - - matched.push([pattern, settings]); - - if (!multiple) - return false; -} - -function query(url, multiple) -{ - const matched = []; - for_each_possible_pattern(url, p => check_pattern(p, multiple, matched)); - - return multiple ? matched : (matched[0] || [undefined, undefined]); -} - -function query_best(url) -{ - return query(url, false); -} - -function query_all(url) -{ - return query(url, true); -} - -const get_query_best = make_once(() => init(query_best)); -const get_query_all = make_once(() => init(query_all)); - -/* - * EXPORTS_START - * EXPORT get_query_best - * EXPORT get_query_all - * EXPORTS_END - */ diff --git a/common/settings_query.js b/common/settings_query.js new file mode 100644 index 0000000..e85ae63 --- /dev/null +++ b/common/settings_query.js @@ -0,0 +1,52 @@ +/** + * Hachette querying page settings with regard to wildcard records + * + * Copyright (C) 2021 Wojtek Kosior + * Redistribution terms are gathered in the `copyright' file. + */ + +/* + * IMPORTS_START + * IMPORT TYPE_PREFIX + * IMPORT for_each_possible_pattern + * IMPORTS_END + */ + +function check_pattern(storage, pattern, multiple, matched) +{ + const settings = storage.get(TYPE_PREFIX.PAGE, pattern); + + if (settings === undefined) + return; + + matched.push([pattern, settings]); + + if (!multiple) + return false; +} + +function query(storage, url, multiple) +{ + const matched = []; + const cb = p => check_pattern(storage, p, multiple, matched); + for_each_possible_pattern(url, cb); + + return multiple ? matched : (matched[0] || [undefined, undefined]); +} + +function query_best(storage, url) +{ + return query(storage, url, false); +} + +function query_all(storage, url) +{ + return query(storage, url, true); +} + +/* + * EXPORTS_START + * EXPORT query_best + * EXPORT query_all + * EXPORTS_END + */ -- cgit v1.2.3