aboutsummaryrefslogtreecommitdiff
path: root/test-env.in
blob: a7f506ec1923c559e16c127accd9458a44cc597d (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
#!/bin/sh

# GNU Guix --- Functional package management for GNU
# Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
#
# This file is part of GNU Guix.
#
# GNU Guix is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or (at
# your option) any later version.
#
# GNU Guix is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

# Usage: ./test-env COMMAND ARG...
#
# Run the daemon in the build directory, and run COMMAND within
# `pre-inst-env'.  This is used to run unit tests with the just-built
# daemon, unless `--disable-daemon' was passed at configure time.


# Make sure 'cd' behaves deterministically and doesn't write anything to
# stdout.
unset CDPATH

if [ -x "@abs_top_builddir@/guix-daemon" ]
then
    NIX_SETUID_HELPER="@abs_top_builddir@/nix-setuid-helper" # normally unused
    NIX_STORE_DIR="@GUIX_TEST_ROOT@/store"

    # Do that because store.scm calls `canonicalize-path' on it.
    mkdir -p "$NIX_STORE_DIR"

    # Canonicalize the store directory name in an attempt to avoid symlinks in
    # it or its parent directories.  See <http://bugs.gnu.org/17935>.
    NIX_STORE_DIR="`cd "@GUIX_TEST_ROOT@/store"; pwd -P`"

    NIX_LOCALSTATE_DIR="@GUIX_TEST_ROOT@/var"
    NIX_LOG_DIR="@GUIX_TEST_ROOT@/var/log/guix"
    NIX_DB_DIR="@GUIX_TEST_ROOT@/db"
    NIX_ROOT_FINDER="@abs_top_builddir@/nix/scripts/list-runtime-roots"

    # Choose a PID-dependent name to allow for parallel builds.  Note
    # that the directory name must be chosen so that the socket's file
    # name is less than 108-char long (the size of `sun_path' in glibc).
    # Currently, in Nix builds, we're at ~106 chars...
    NIX_STATE_DIR="@GUIX_TEST_ROOT@/var/$$"

    # We can't exit when we reach the limit, because perhaps the test doesn't
    # actually rely on the daemon, but at least warn.
    if test "`echo -n "$NIX_STATE_DIR/daemon-socket/socket" | wc -c`" -ge 108
    then
	echo "warning: exceeding socket file name limit; test may fail!" >&2
    fi

    # The configuration directory, for import/export signing keys.
    NIX_CONF_DIR="@GUIX_TEST_ROOT@/etc"
    if [ ! -d "$NIX_CONF_DIR" ]
    then
	# Copy the keys so that the secret key has the right permissions (the
	# daemon errors out when this is not the case.)
	mkdir -p "$NIX_CONF_DIR"
	cp "@abs_top_srcdir@/tests/signing-key.sec"	\
	    "@abs_top_srcdir@/tests/signing-key.pub"	\
	    "$NIX_CONF_DIR"
	chmod 400 "$NIX_CONF_DIR/signing-key.sec"
    fi

    # A place to store data of the substituter.
    GUIX_BINARY_SUBSTITUTE_URL="file://$NIX_STATE_DIR/substituter-data"
    rm -rf "$NIX_STATE_DIR/substituter-data"
    mkdir -p "$NIX_STATE_DIR/substituter-data"

    # For a number of tests, we want to allow unsigned narinfos, for
    # simplicity.
    GUIX_ALLOW_UNAUTHENTICATED_SUBSTITUTES=yes

    # Place for the substituter's cache.
    XDG_CACHE_HOME="$NIX_STATE_DIR/cache-$$"

    export NIX_IGNORE_SYMLINK_STORE NIX_STORE_DIR			\
	NIX_LOCALSTATE_DIR NIX_LOG_DIR NIX_STATE_DIR NIX_DB_DIR		\
	NIX_ROOT_FINDER NIX_SETUID_HELPER GUIX_BINARY_SUBSTITUTE_URL	\
        GUIX_ALLOW_UNAUTHENTICATED_SUBSTITUTES				\
        NIX_CONF_DIR XDG_CACHE_HOME

    # Launch the daemon without chroot support because is may be
    # unavailable, for instance if we're not running as root.
    "@abs_top_builddir@/pre-inst-env"				\
	"@abs_top_builddir@/guix-daemon" --disable-chroot	\
	--substitute-urls="$GUIX_BINARY_SUBSTITUTE_URL" &

    daemon_pid=$!
    trap "kill $daemon_pid ; rm -rf $NIX_STATE_DIR" EXIT
fi

# Avoid issues that could stem from l10n, such as language/encoding
# mismatches.
unset LANGUAGE
LC_MESSAGES=C
export LC_MESSAGES

# Ignore user settings.
unset GUIX_PACKAGE_PATH GUIX_BUILD_OPTIONS

storedir="@storedir@"
prefix="@prefix@"
datarootdir="@datarootdir@"
datadir="@datadir@"
localstatedir="@localstatedir@"
export storedir prefix datarootdir datadir localstatedir

"@abs_top_builddir@/pre-inst-env" "$@"
exit $?
36' href='#n236'>236 237 238 239
/**
 * Hachette display panel logic
 *
 * Copyright (C) 2021 Wojtek Kosior
 * Redistribution terms are gathered in the `copyright' file.
 */

/*
 * IMPORTS_START
 * IMPORT browser
 * IMPORT is_chrome
 * IMPORT is_mozilla
 * IMPORT CONNECTION_TYPE
 * IMPORT url_item
 * IMPORT is_privileged_url
 * IMPORT TYPE_PREFIX
 * IMPORT nice_name
 * IMPORT open_in_settings
 * IMPORT for_each_possible_pattern
 * IMPORTS_END
 */

function by_id(id)
{
    return document.getElementById(id);
}

const tab_query = {currentWindow: true, active: true};

async function get_current_tab()
{
    /* Fix for fact that Chrome does not use promises here */
    const promise = is_chrome ?
	  new Promise((resolve, reject) =>
		      browser.tabs.query(tab_query, tab => resolve(tab))) :
	  browser.tabs.query(tab_query);

    try {
	return (await promise)[0];
    } catch(e) {
	console.log(e);
    }
}

const page_url_heading = by_id("page_url_heading");
const show_privileged_notice_chbx = by_id("show_privileged_notice_chbx");
const show_page_state_chbx = by_id("show_page_state_chbx");

async function show_page_activity_info()
{
    const tab = await get_current_tab();

    if (tab === undefined) {
	page_url_heading.textContent = "unknown page";
	return;
    }

    const url = url_item(tab.url);
    page_url_heading.textContent = url;
    if (is_privileged_url(url)) {
	show_privileged_notice_chbx.checked = true;
	return;
    }

    populate_possible_patterns_list(url);
    show_page_state_chbx.checked = true;

    try_to_connect(tab.id);
}

function populate_possible_patterns_list(url)
{
    for_each_possible_pattern(url, add_pattern_to_list);

    const port = browser.runtime.connect({name: CONNECTION_TYPE.PAGE_INFO});
    port.onMessage.addListener(handle_page_info);
    port.postMessage(["subscribe", url]);
}

const possible_patterns_ul = by_id("possible_patterns");
const pattern_li_template = by_id("pattern_li_template");
pattern_li_template.removeAttribute("id");
const known_patterns = new Map();

function add_pattern_to_list(pattern)
{
    const li = pattern_li_template.cloneNode(true);
    li.id = `pattern_li_${known_patterns.size}`;
    known_patterns.set(pattern, li.id);

    const span = li.firstElementChild;
    span.textContent = pattern;

    const button = span.nextElementSibling;
    const settings_opener = () => open_in_settings(TYPE_PREFIX.PAGE, pattern);
    button.addEventListener("click", settings_opener);

    possible_patterns_ul.appendChild(li)

    return li.id;
}

function ensure_pattern_exists(pattern)
{
    let id = known_patterns.get(pattern);
    /*
     * As long as pattern computation works well, we should never get into this
     * conditional block. This is just a safety measure. To be removed as part
     * of a bigger rework when we start taking iframes into account.
     */
    if (id === undefined) {
	console.log(`unknown pattern: ${pattern}`);
	id = add_pattern_to_list(pattern);
    }

    return id;
}

function set_pattern_li_button_text(li_id, text)
{
    by_id(li_id).firstElementChild.nextElementSibling.textContent = text;
}

function handle_page_info(message)
{
    const [type, data] = message;

    if (type === "change") {
	const li_id = ensure_pattern_exists(data.item);
	if (data.old_val === undefined)
	    set_pattern_li_button_text(li_id, "Edit in settings");
	if (data.new_val === undefined)
	    set_pattern_li_button_text(li_id, "Add setting");
    }

    if (type === "new_url") {
	for (const li_id of known_patterns.values())
	    set_pattern_li_button_text(li_id, "Add setting");
	for (const [pattern, settings] of data) {
	    set_pattern_li_button_text(ensure_pattern_exists(pattern),
				       "Edit in settings")
	}
    }
}

const connected_chbx = by_id("connected_chbx");

function try_to_connect(tab_id)
{
    /* This won't connect to iframes. We'll add support for them later */
    const connect_info = {name: CONNECTION_TYPE.ACTIVITY_INFO, frameId: 0};
    const port = browser.tabs.connect(tab_id, connect_info);

    port.onDisconnect.addListener(port => handle_disconnect(tab_id));
    port.onMessage.addListener(handle_activity_report);

    if (is_mozilla)
	setTimeout(() => monitor_connecting(port, tab_id), 1000);
}

const loading_chbx = by_id("loading_chbx");

function handle_disconnect(tab_id)
{
    if (is_chrome && !browser.runtime.lastError)
	return;

    /* return if there was no connection initialization failure */
    if (connected_chbx.checked)
	return;

    loading_chbx.checked = !loading_chbx.checked;
    setTimeout(() => try_to_connect(tab_id), 1000);
}

function monitor_connecting(port, tab_id)
{
    if (connected_chbx.checked)
	return;

    port.disconnect();
    loading_chbx.checked = !loading_chbx.checked;
    try_to_connect(tab_id);
}

const pattern_span = by_id("pattern");
const view_pattern_but = by_id("view_pattern");
const blocked_span = by_id("blocked");
const payload_span = by_id("payload");
const view_payload_but = by_id("view_payload");
const container_for_injected = by_id("container_for_injected");

function handle_activity_report(message)
{
    connected_chbx.checked = true;

    const [type, data] = message;

    if (type === "settings") {
	let [pattern, settings] = data;

	settings = settings || {};
	blocked_span.textContent = settings.allow ? "no" : "yes";

	if (pattern) {
	    pattern_span.textContent = pattern;
	    const settings_opener =
		  () => open_in_settings(TYPE_PREFIX.PAGE, pattern);
	    view_pattern_but.classList.remove("hide");
	    view_pattern_but.addEventListener("click", settings_opener);
	} else {
	    pattern_span.textContent = "none";
	}

	const components = settings.components;
	if (components) {
	    payload_span.textContent = nice_name(...components);
	    const settings_opener = () => open_in_settings(...components);
	    view_payload_but.classList.remove("hide");
	    view_payload_but.addEventListener("click", settings_opener);
	} else {
	    payload_span.textContent = "none";
	}
    }
    if (type === "script") {
	const h4 = document.createElement("h4");
	const pre = document.createElement("pre");
	h4.textContent = "script";
	pre.textContent = data;

	container_for_injected.appendChild(h4);
	container_for_injected.appendChild(pre);
    }
}

by_id("settings_but")
    .addEventListener("click", (e) => browser.runtime.openOptionsPage());

show_page_activity_info();