aboutsummaryrefslogtreecommitdiff
path: root/background/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'background/main.js')
-rw-r--r--background/main.js238
1 files changed, 0 insertions, 238 deletions
diff --git a/background/main.js b/background/main.js
deleted file mode 100644
index 61c96ac..0000000
--- a/background/main.js
+++ /dev/null
@@ -1,238 +0,0 @@
-/**
- * This file is part of Haketilo.
- *
- * Function: Main background script.
- *
- * Copyright (C) 2021 Wojtek Kosior <koszko@koszko.org>
- * Copyright (C) 2021 Jahoti <jahoti@envs.net>
- *
- * This program 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.
- *
- * This program 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.
- *
- * As additional permission under GNU GPL version 3 section 7, you
- * may distribute forms of that code without the copy of the GNU
- * GPL normally required by section 4, provided you include this
- * license notice and, in case of non-source distribution, a URL
- * through which recipients can access the Corresponding Source.
- * If you modify file(s) with this exception, you may extend this
- * exception to your version of the file(s), but you are not
- * obligated to do so. If you do not wish to do so, delete this
- * exception statement from your version.
- *
- * As a special exception to the GPL, any HTML file which merely
- * makes function calls to this code, and for that purpose
- * includes it by reference shall be deemed a separate work for
- * copyright law purposes. If you modify this code, you may extend
- * this exception to your version of the code, but you are not
- * obligated to do so. If you do not wish to do so, delete this
- * exception statement from your version.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * I, Wojtek Kosior, thereby promise not to sue for violation of this file's
- * license. Although I request that you do not make use of this code in a
- * proprietary program, I am not going to enforce this in court.
- */
-
-#IMPORT common/storage_light.js AS light_storage
-
-#IMPORT background/storage_server.js
-#IMPORT background/page_actions_server.js
-#IMPORT background/stream_filter.js
-
-#FROM common/browser.js IMPORT browser
-#FROM common/stored_types.js IMPORT TYPE_PREFIX
-#FROM background/storage.js IMPORT get_storage
-#FROM common/misc.js IMPORT is_privileged_url
-#FROM common/settings_query.js IMPORT query_best
-#FROM background/policy_injector.js IMPORT inject_csp_headers
-
-const initial_data = (
-#INCLUDE_VERBATIM default_settings.json
-);
-
-storage_server.start();
-page_actions_server.start();
-
-async function init_ext(install_details)
-{
- if (install_details.reason != "install")
- return;
-
- let storage = await get_storage();
-
- await storage.clear();
-
- /* Below we add sample settings to the extension. */
- for (let setting of initial_data) {
- let [key, value] = Object.entries(setting)[0];
- storage.set(key[0], key.substring(1), value);
- }
-}
-
-browser.runtime.onInstalled.addListener(init_ext);
-
-/*
- * The function below implements a more practical interface for what it does by
- * wrapping the old query_best() function.
- */
-function decide_policy_for_url(storage, policy_observable, url)
-{
- if (storage === undefined)
- return {allow: false};
-
- const settings =
- {allow: policy_observable !== undefined && policy_observable.value};
-
- const [pattern, queried_settings] = query_best(storage, url);
-
- if (queried_settings) {
- settings.payload = queried_settings.components;
- settings.allow = !!queried_settings.allow && !settings.payload;
- settings.pattern = pattern;
- }
-
- return settings;
-}
-
-let storage;
-let policy_observable = {};
-
-function sanitize_web_page(details)
-{
- const url = details.url;
- if (is_privileged_url(details.url))
- return;
-
- const policy =
- decide_policy_for_url(storage, policy_observable, details.url);
-
- let headers = details.responseHeaders;
-
- headers = inject_csp_headers(headers, policy);
-
- let skip = false;
- for (const header of headers) {
- if ((header.name.toLowerCase().trim() === "content-disposition" &&
- /^\s*attachment\s*(;.*)$/i.test(header.value)))
- skip = true;
- }
- skip = skip || (details.statusCode >= 300 && details.statusCode < 400);
-
- if (!skip) {
- /* Check for API availability. */
- if (browser.webRequest.filterResponseData)
- headers = stream_filter.apply(details, headers, policy);
- }
-
- return {responseHeaders: headers};
-}
-
-const request_url_regex = /^[^?]*\?url=(.*)$/;
-const redirect_url_template = browser.runtime.getURL("dummy") + "?settings=";
-
-function synchronously_smuggle_policy(details)
-{
- /*
- * Content script will make a synchronous XmlHttpRequest to extension's
- * `dummy` file to query settings for given URL. We smuggle that
- * information in query parameter of the URL we redirect to.
- * A risk of fingerprinting arises if a page with script execution allowed
- * guesses the dummy file URL and makes an AJAX call to it. It is currently
- * a problem in ManifestV2 Chromium-family port of Haketilo because Chromium
- * uses predictable URLs for web-accessible resources. We plan to fix it in
- * the future ManifestV3 port.
- */
- if (details.type !== "xmlhttprequest")
- return {cancel: true};
-
- console.debug(`Settings queried using XHR for '${details.url}'.`);
-
- let policy = {allow: false};
-
- try {
- /*
- * request_url should be of the following format:
- * <url_for_extension's_dummy_file>?url=<valid_urlencoded_url>
- */
- const match = request_url_regex.exec(details.url);
- const queried_url = decodeURIComponent(match[1]);
-
- if (details.initiator && !queried_url.startsWith(details.initiator)) {
- console.warn(`Blocked suspicious query of '${url}' by '${details.initiator}'. This might be the result of page fingerprinting the browser.`);
- return {cancel: true};
- }
-
- policy = decide_policy_for_url(storage, policy_observable, queried_url);
- } catch (e) {
- console.warn(`Bad request! Expected ${browser.runtime.getURL("dummy")}?url=<valid_urlencoded_url>. Got ${request_url}. This might be the result of page fingerprinting the browser.`);
- }
-
- const encoded_policy = encodeURIComponent(JSON.stringify(policy));
-
- return {redirectUrl: redirect_url_template + encoded_policy};
-}
-
-const all_types = [
- "main_frame", "sub_frame", "stylesheet", "script", "image", "font",
- "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket",
- "other", "main_frame", "sub_frame"
-];
-
-async function start_webRequest_operations()
-{
- storage = await get_storage();
-
-#IF CHROMIUM
- const extra_opts = ["blocking", "extraHeaders"];
-#ELSE
- const extra_opts = ["blocking"];
-#ENDIF
-
- browser.webRequest.onHeadersReceived.addListener(
- sanitize_web_page,
- {urls: ["<all_urls>"], types: ["main_frame", "sub_frame"]},
- extra_opts.concat("responseHeaders")
- );
-
- const dummy_url_pattern = browser.runtime.getURL("dummy") + "?url=*";
- browser.webRequest.onBeforeRequest.addListener(
- synchronously_smuggle_policy,
- {urls: [dummy_url_pattern], types: ["xmlhttprequest"]},
- extra_opts
- );
-
- policy_observable = await light_storage.observe_var("default_allow");
-}
-
-start_webRequest_operations();
-
-#IF MOZILLA
-const code = `\
-console.warn("Hi, I'm Mr Dynamic!");
-
-console.debug("let's see how window.haketilo_exports looks like now");
-
-console.log("haketilo_exports", window.haketilo_exports);
-`
-
-async function test_dynamic_content_scripts()
-{
- browser.contentScripts.register({
- "js": [{code}],
- "matches": ["<all_urls>"],
- "allFrames": true,
- "runAt": "document_start"
-});
-}
-
-test_dynamic_content_scripts();
-#ENDIF