Project

General

Profile

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

haketilo / background / page_actions_server.js @ 261548ff

1
/**
2
 * Myext serving of page actions to content scripts
3
 *
4
 * Copyright (C) 2021 Wojtek Kosior
5
 * Redistribution terms are gathered in the `copyright' file.
6
 */
7

    
8
/*
9
 * IMPORTS_START
10
 * IMPORT get_storage
11
 * IMPORT TYPE_PREFIX
12
 * IMPORT CONNECTION_TYPE
13
 * IMPORT browser
14
 * IMPORT listen_for_connection
15
 * IMPORT sha256
16
 * IMPORT get_query_best
17
 * IMPORTS_END
18
 */
19

    
20
var storage;
21
var query_best;
22
var handler;
23

    
24
function send_scripts(url, port)
25
{
26
    let [pattern, settings] = query_best(url);
27
    if (settings === undefined)
28
	return;
29

    
30
    let components = settings.components;
31
    let processed_bags = new Set();
32

    
33
    if (components !== undefined)
34
	send_scripts_rec([components], port, processed_bags);
35
}
36

    
37
// TODO: parallelize script fetching
38
async function send_scripts_rec(components, port, processed_bags)
39
{
40
    for (let [prefix, name] of components) {
41
	if (prefix === TYPE_PREFIX.BAG) {
42
	    if (processed_bags.has(name)) {
43
		console.log(`preventing recursive inclusion of bag ${name}`);
44
		continue;
45
	    }
46

    
47
	    var bag = storage.get(TYPE_PREFIX.BAG, name);
48

    
49
	    if (bag === undefined) {
50
		console.log(`no bag in storage for key ${name}`);
51
		continue;
52
	    }
53

    
54
	    processed_bags.add(name);
55
	    await send_scripts_rec(bag, port, processed_bags);
56
	    processed_bags.delete(name);
57
	} else {
58
	    let script_text = await get_script_text(name);
59
	    if (script_text === undefined)
60
		continue;
61

    
62
	    port.postMessage({inject : [script_text]});
63
	}
64
    }
65
}
66

    
67
async function get_script_text(script_name)
68
{
69
    try {
70
	let script_data = storage.get(TYPE_PREFIX.SCRIPT, script_name);
71
	if (script_data === undefined) {
72
	    console.log(`missing data for ${script_name}`);
73
	    return;
74
	}
75
	let script_text = script_data.text;
76
	if (!script_text)
77
	    script_text = await fetch_remote_script(script_data);
78
	return script_text;
79
    } catch (e) {
80
	console.log(e);
81
    }
82
}
83

    
84
function ajax_callback()
85
{
86
    if (this.readyState == 4)
87
	this.resolve_callback(this);
88
}
89

    
90
function initiate_ajax_request(resolve, method, url)
91
{
92
    var xhttp = new XMLHttpRequest();
93
    xhttp.resolve_callback = resolve;
94
    xhttp.onreadystatechange = ajax_callback;
95
    xhttp.open(method, url, true);
96
    xhttp.send();
97
}
98

    
99
function make_ajax_request(method, url)
100
{
101
    return new Promise((resolve, reject) =>
102
		       initiate_ajax_request(resolve, method, url));
103
}
104

    
105
async function fetch_remote_script(script_data)
106
{
107
    try {
108
	let xhttp = await make_ajax_request("GET", script_data.url);
109
	if (xhttp.status === 200) {
110
	    let computed_hash = sha256(xhttp.responseText);
111
	    if (computed_hash !== script_data.hash) {
112
		console.log(`Bad hash for ${script_data.url}\n    got ${computed_hash} instead of ${script_data.hash}`);
113
		return;
114
	    }
115
	    return xhttp.responseText;
116
	} else {
117
	    console.log("script not fetched: " + script_data.url);
118
	    return;
119
	}
120
    } catch (e) {
121
	console.log(e);
122
    }
123
}
124

    
125
function handle_message(port, message, handler)
126
{
127
    port.onMessage.removeListener(handler[0]);
128
    let url = message.url;
129
    console.log({url});
130
    send_scripts(url, port);
131
}
132

    
133
function new_connection(port)
134
{
135
    console.log("new page actions connection!");
136
    let handler = [];
137
    handler.push(m => handle_message(port, m, handler));
138
    port.onMessage.addListener(handler[0]);
139
}
140

    
141
async function start_page_actions_server()
142
{
143
    storage = await get_storage();
144
    query_best = await get_query_best();
145

    
146
    listen_for_connection(CONNECTION_TYPE.PAGE_ACTIONS, new_connection);
147
}
148

    
149
/*
150
 * EXPORTS_START
151
 * EXPORT start_page_actions_server
152
 * EXPORTS_END
153
 */
(3-3/7)