aboutsummaryrefslogtreecommitdiff
path: root/gnu/packages/pantheon.scm
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages/pantheon.scm')
0 files changed, 0 insertions, 0 deletions
/a> 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/**
 * Hachette serving of page actions to content scripts
 *
 * Copyright (C) 2021 Wojtek Kosior
 * Redistribution terms are gathered in the `copyright' file.
 */

/*
 * IMPORTS_START
 * IMPORT get_storage
 * IMPORT TYPE_PREFIX
 * IMPORT CONNECTION_TYPE
 * IMPORT browser
 * IMPORT listen_for_connection
 * IMPORT sha256
 * IMPORT get_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 repos = storage.get_all(TYPE_PREFIX.REPO);

    port.postMessage(["settings", [pattern, settings, repos]]);

    if (settings === undefined)
	return;

    let components = settings.components;
    let processed_bags = new Set();

    if (components !== undefined)
	send_scripts([components], port, processed_bags);
}

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

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

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

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

	    processed_bags.delete(name);
	} else {
	    let script_text = await get_script_text(name);
	    if (script_text === undefined)
		continue;

	    port.postMessage(["inject", [script_text]]);
	}
    }
}

async function get_script_text(script_name)
{
    try {
	let script_data = storage.get(TYPE_PREFIX.SCRIPT, script_name);
	if (script_data === undefined) {
	    console.log(`missing data for ${script_name}`);
	    return;
	}
	let script_text = script_data.text;
	if (!script_text)
	    script_text = await fetch_remote_script(script_data);
	return script_text;
    } catch (e) {
	console.log(e);
    }
}

async function fetch_remote_script(script_data)
{
    try {
	let xhttp = await make_ajax_request("GET", script_data.url);
	if (xhttp.status === 200) {
	    let computed_hash = sha256(xhttp.responseText);
	    if (computed_hash !== script_data.hash) {
		console.log(`Bad hash for ${script_data.url}\n    got ${computed_hash} instead of ${script_data.hash}`);
		return;
	    }
	    return xhttp.responseText;
	} else {
	    console.log("script not fetched: " + script_data.url);
	    return;
	}
    } catch (e) {
	console.log(e);
    }
}

function handle_message(port, message, handler)
{
    port.onMessage.removeListener(handler[0]);
    let url = message.url;
    console.log({url});
    send_actions(url, port);
}

function new_connection(port)
{
    console.log("new page actions connection!");
    let handler = [];
    handler.push(m => handle_message(port, m, handler));
    port.onMessage.addListener(handler[0]);
}

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);
}

/*
 * EXPORTS_START
 * EXPORT start_page_actions_server
 * EXPORTS_END
 */