Project

General

Profile

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

haketilo / background / main.js @ 6247f163

1
/**
2
 * Hachette main background script
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 light_storage
13
 * IMPORT start_storage_server
14
 * IMPORT start_page_actions_server
15
 * IMPORT browser
16
 * IMPORT is_privileged_url
17
 * IMPORT query_best
18
 * IMPORT gen_nonce
19
 * IMPORT inject_csp_headers
20
 * IMPORT apply_stream_filter
21
 * IMPORT filter_cookie_headers
22
 * IMPORT is_chrome
23
 * IMPORTS_END
24
 */
25

    
26
start_storage_server();
27
start_page_actions_server();
28

    
29
async function init_ext(install_details)
30
{
31
    if (install_details.reason != "install")
32
	return;
33

    
34
    let storage = await get_storage();
35

    
36
    await storage.clear();
37

    
38
    /*
39
     * Below we add sample settings to the extension.
40
     */
41

    
42
    for (let setting of // The next line is replaced with the contents of /default_settings.json by the build script
43
        `DEFAULT SETTINGS`
44
    ) {
45
	let [key, value] = Object.entries(setting)[0];
46
	storage.set(key[0], key.substring(1), value);
47
    }
48
}
49

    
50
browser.runtime.onInstalled.addListener(init_ext);
51

    
52

    
53
let storage;
54
let policy_observable = {};
55

    
56
function on_headers_received(details)
57
{
58
    const url = details.url;
59
    if (is_privileged_url(details.url))
60
	return;
61

    
62
    const [pattern, settings] = query_best(storage, details.url);
63
    const allow = !!(settings ? settings.allow : policy_observable.value);
64
    const nonce = gen_nonce();
65
    const policy = {allow, url, nonce};
66

    
67
    let headers = details.responseHeaders;
68
    let skip = false;
69
    for (const header of headers) {
70
	if ((header.name.toLowerCase().trim() === "content-disposition" &&
71
	     /^\s*attachment\s*(;.*)$/i.test(header.value)))
72
	    skip = true;
73
    }
74

    
75
    headers = inject_csp_headers(headers, policy);
76

    
77
    skip = skip || (details.statusCode >= 300 && details.statusCode < 400);
78
    if (!skip) {
79
	/* Check for API availability. */
80
	if (browser.webRequest.filterResponseData)
81
	    headers = apply_stream_filter(details, headers, policy);
82
    }
83

    
84
    return {responseHeaders: headers};
85
}
86

    
87
function on_before_send_headers(details)
88
{
89
    let headers = details.requestHeaders;
90
    headers = filter_cookie_headers(headers);
91
    return {requestHeaders: headers};
92
}
93

    
94
const all_types = [
95
    "main_frame", "sub_frame", "stylesheet", "script", "image", "font",
96
    "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket",
97
    "other", "main_frame", "sub_frame"
98
];
99

    
100
async function start_webRequest_operations()
101
{
102
    storage = await get_storage();
103

    
104
    const extra_opts = ["blocking"];
105
    if (is_chrome)
106
	extra_opts.push("extraHeaders");
107

    
108
    browser.webRequest.onHeadersReceived.addListener(
109
	on_headers_received,
110
	{urls: ["<all_urls>"], types: ["main_frame", "sub_frame"]},
111
	extra_opts.concat("responseHeaders")
112
    );
113

    
114
    browser.webRequest.onBeforeSendHeaders.addListener(
115
	on_before_send_headers,
116
	{urls: ["<all_urls>"], types: all_types},
117
	extra_opts.concat("requestHeaders")
118
    );
119

    
120
    policy_observable = await light_storage.observe_var("default_allow");
121
}
122

    
123
start_webRequest_operations();
(2-2/7)