Project

General

Profile

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

haketilo / background / page_actions_server.js @ 96068ada

1
/**
2
 * This file is part of Haketilo.
3
 *
4
 * Function: Serving page actions to content scripts.
5
 *
6
 * Copyright (C) 2021 Wojtek Kosior
7
 * Redistribution terms are gathered in the `copyright' file.
8
 */
9

    
10
/*
11
 * IMPORTS_START
12
 * IMPORT get_storage
13
 * IMPORT light_storage
14
 * IMPORT TYPE_PREFIX
15
 * IMPORT CONNECTION_TYPE
16
 * IMPORT browser
17
 * IMPORT listen_for_connection
18
 * IMPORT sha256
19
 * IMPORT make_ajax_request
20
 * IMPORTS_END
21
 */
22

    
23
var storage;
24
var handler;
25

    
26
// TODO: parallelize script fetching
27
async function send_scripts(components, port, processed_bags)
28
{
29
    for (let [prefix, name] of components) {
30
	if (prefix === TYPE_PREFIX.BAG) {
31
	    if (processed_bags.has(name)) {
32
		console.log(`preventing recursive inclusion of bag ${name}`);
33
		continue;
34
	    }
35

    
36
	    var bag = storage.get(TYPE_PREFIX.BAG, name);
37

    
38
	    if (bag === undefined) {
39
		console.log(`no bag in storage for key ${name}`);
40
		continue;
41
	    }
42

    
43
	    processed_bags.add(name);
44
	    await send_scripts(bag, port, processed_bags);
45

    
46
	    processed_bags.delete(name);
47
	} else {
48
	    let script_text = await get_script_text(name);
49
	    if (script_text === undefined)
50
		continue;
51

    
52
	    port.postMessage(["inject", [script_text]]);
53
	}
54
    }
55
}
56

    
57
async function get_script_text(script_name)
58
{
59
    try {
60
	let script_data = storage.get(TYPE_PREFIX.SCRIPT, script_name);
61
	if (script_data === undefined) {
62
	    console.log(`missing data for ${script_name}`);
63
	    return;
64
	}
65
	let script_text = script_data.text;
66
	if (!script_text)
67
	    script_text = await fetch_remote_script(script_data);
68
	return script_text;
69
    } catch (e) {
70
	console.log(e);
71
    }
72
}
73

    
74
async function fetch_remote_script(script_data)
75
{
76
    try {
77
	let xhttp = await make_ajax_request("GET", script_data.url);
78
	if (xhttp.status === 200) {
79
	    let computed_hash = sha256(xhttp.responseText);
80
	    if (computed_hash !== script_data.hash) {
81
		console.log(`Bad hash for ${script_data.url}\n    got ${computed_hash} instead of ${script_data.hash}`);
82
		return;
83
	    }
84
	    return xhttp.responseText;
85
	} else {
86
	    console.log("script not fetched: " + script_data.url);
87
	    return;
88
	}
89
    } catch (e) {
90
	console.log(e);
91
    }
92
}
93

    
94
function handle_message(port, message, handler)
95
{
96
    port.onMessage.removeListener(handler[0]);
97
    console.debug(`Loading payload '${message.payload}'.`);
98

    
99
    const processed_bags = new Set();
100

    
101
    send_scripts([message.payload], port, processed_bags);
102
}
103

    
104
function new_connection(port)
105
{
106
    console.log("new page actions connection!");
107
    let handler = [];
108
    handler.push(m => handle_message(port, m, handler));
109
    port.onMessage.addListener(handler[0]);
110
}
111

    
112
async function start_page_actions_server()
113
{
114
    storage = await get_storage();
115

    
116
    listen_for_connection(CONNECTION_TYPE.PAGE_ACTIONS, new_connection);
117
}
118

    
119
/*
120
 * EXPORTS_START
121
 * EXPORT start_page_actions_server
122
 * EXPORTS_END
123
 */
(2-2/6)