Project

General

Profile

Download (1.92 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / background / policy_injector.js @ dcfc78b0

1
/**
2
 * Myext injecting policy to page using webRequest
3
 *
4
 * Copyright (C) 2021 Wojtek Kosior
5
 * Redistribution terms are gathered in the `copyright' file.
6
 */
7

    
8
/*
9
 * IMPORTS_START
10
 * IMPORT TYPE_PREFIX
11
 * IMPORT get_storage
12
 * IMPORT browser
13
 * IMPORT is_chrome
14
 * IMPORT retrieve_nonce
15
 * IMPORT url_item
16
 * IMPORT get_query_best
17
 * IMPORT csp_rule
18
 * IMPORTS_END
19
 */
20

    
21
var storage;
22
var query_best;
23

    
24
const csp_header_names = {
25
    "content-security-policy" : true,
26
    "x-webkit-csp" : true,
27
    "x-content-security-policy" : true
28
};
29

    
30
const header_name = "content-security-policy";
31

    
32
function is_csp_header(header)
33
{
34
    return !!csp_header_names[header.name.toLowerCase()];
35
}
36

    
37
function is_our_header(header, rule)
38
{
39
    return header.value === rule
40
}
41

    
42
function inject(details)
43
{
44
    const url = url_item(details.url);
45

    
46
    const [pattern, settings] = query_best(url);
47

    
48
    const nonce = retrieve_nonce(details.tabId, details.frameId, true);
49
    const rule = csp_rule(nonce);
50

    
51
    var headers;
52

    
53
    if (settings !== undefined && settings.allow) {
54
	/*
55
	 * Chrome doesn't have the buggy behavior of repeatedly injecting a
56
	 * header we injected once. Firefox does and we have to remove it there.
57
	 */
58
	if (is_chrome)
59
	    return {cancel: false};
60

    
61
	headers = details.responseHeaders.filter(h => !is_our_header(h, rule));
62
    } else {
63
	headers = details.responseHeaders.filter(h => !is_csp_header(h));
64

    
65
	headers.push({
66
	    name : header_name,
67
	    value : rule
68
	});
69
    }
70

    
71
    return {responseHeaders: headers};
72
}
73

    
74
async function start_policy_injector()
75
{
76
    storage = await get_storage();
77
    query_best = await get_query_best();
78

    
79
    let extra_opts = ["blocking", "responseHeaders"];
80
    if (is_chrome)
81
	extra_opts.push("extraHeaders");
82

    
83
    browser.webRequest.onHeadersReceived.addListener(
84
	inject,
85
	{
86
	    urls: ["<all_urls>"],
87
	    types: ["main_frame", "sub_frame"]
88
	},
89
	extra_opts
90
    );
91
}
92

    
93
/*
94
 * EXPORTS_START
95
 * EXPORT start_policy_injector
96
 * EXPORTS_END
97
 */
(6-6/9)