From 7e531cf6ba799cffc63783fb12a63d1be6c4a885 Mon Sep 17 00:00:00 2001
From: Dominik Hebeler <dominik@suma-ev.de>
Date: Thu, 14 Mar 2024 14:21:13 +0100
Subject: [PATCH] make sure background script is restarted when paused

---
 build/js/Cookie.js          | 49 ++++++++++++++++++++++++
 build/js/SettingsManager.js | 75 +++++++++----------------------------
 build/js/app.js             | 51 ++++++++++++++++++++++++-
 manifest.json               |  4 +-
 web/settings/index.js       |  2 +-
 5 files changed, 120 insertions(+), 61 deletions(-)

diff --git a/build/js/Cookie.js b/build/js/Cookie.js
index f0e9b02..adcc4a6 100644
--- a/build/js/Cookie.js
+++ b/build/js/Cookie.js
@@ -43,4 +43,53 @@ export class Cookie {
             this.expired = true;
         }
     }
+
+    static async COOKIES_TO_SETTINGS() {
+        let cookie_settings = {};
+        // First fetch all cookies from metager.org
+        await browser.cookies.getAll({ url: "https://metager.org/" }).then(async cookies => {
+            for (let cookie of cookies) {
+                cookie_settings[cookie.name] = cookie.value;
+                await browser.cookies.remove({ name: cookie.name, url: "https://metager.org/" });
+            }
+        });
+        await browser.cookies.getAll({ url: "https://metager.de/" }).then(async cookies => {
+            for (let cookie of cookies) {
+                cookie_settings[cookie.name] = cookie.value;
+                await browser.cookies.remove({ name: cookie.name, url: "https://metager.de/" });
+            }
+        });
+
+        // Get the current settings and overwrite the values from existing cookies
+        return browser.storage.sync.get({ settings_settings: {} }).then(storage => {
+            let settings = storage.settings_settings;
+            for (let key in cookie_settings) {
+                settings[key] = cookie_settings[key];
+            }
+            return browser.storage.sync.set({ settings_settings: settings });
+        });
+    }
+
+    static async SETTINGS_TO_COOKIES() {
+        return browser.storage.sync.get({ settings_settings: {} }).then(async storage => {
+            for (let key in storage.settings_settings) {
+                let value = storage.settings_settings[key];
+                let expiration = new Date();
+                expiration.setFullYear(expiration.getFullYear() + 1);
+                await browser.cookies.set({
+                    url: "https://metager.de/",
+                    expirationDate: expiration.getTime(),
+                    secure: true,
+                    name: key,
+                    value: value
+                });
+                await browser.cookies.set({
+                    url: "https://metager.org/",
+                    expirationDate: expiration.getTime(),
+                    name: key,
+                    value: value
+                });
+            }
+        });
+    }
 }
\ No newline at end of file
diff --git a/build/js/SettingsManager.js b/build/js/SettingsManager.js
index 6571218..4a0f59b 100644
--- a/build/js/SettingsManager.js
+++ b/build/js/SettingsManager.js
@@ -2,72 +2,31 @@ import { Cookie } from "./Cookie";
 
 export class SettingsManager {
 
-    _responseListener = this._handleResponseHeaders.bind(this);
-    _requestListener = this._handleRequestHeaders.bind(this);
-
+    store_settings = true;
     settings = {};
 
-    constructor() {
+    async init() {
         // Register event handler for response headers on our domains
         // and fetch current settings from storage
-        browser.storage.sync.get({ settings_store: false, settings_settings: {} }).then(stored_settings => {
+        return browser.storage.sync.get({ settings_store: true, settings_settings: {} }).then(stored_settings => {
+            this.store_settings = stored_settings.settings_store;
             this.settings = stored_settings.settings_settings;
-            if (stored_settings.settings_store == true) {
-                this._toggleRequestListener(true);
-                this._toggleResponseListener(true);
-            }
-        })
-
-        // Listen for changes to the setting storage setting
-        browser.storage.onChanged.addListener((changes, areaName) => {
-            if (changes.hasOwnProperty("settings_store")) {
-                let new_value = changes.settings_store.newValue;
-                this._toggleResponseListener(new_value);
-                this._toggleRequestListener(new_value);
-            }
-            if (changes.hasOwnProperty("settings_settings")) {
-                this.settings = changes.settings_settings.newValue;
-            }
+            return this;
         });
-
-
     }
 
-    _toggleRequestListener(enabled = false) {
-        if (enabled) {
-            browser.webRequest.onBeforeSendHeaders.addListener(
-                this._requestListener,
-                {
-                    urls: [
-                        "https://metager.org/*",
-                        "https://metager.de/*"
-                    ]
-                },
-                ["blocking", "requestHeaders"],
-            );
-        } else {
-            browser.webRequest.onBeforeSendHeaders.removeListener(this._requestListener);
+    handleStorageChange(changes) {
+        if (changes.hasOwnProperty("settings_store") && typeof changes.settings_store.newValue == "boolean") {
+            this.store_settings = changes.settings_store.newValue;
         }
-    }
-
-    _toggleResponseListener(enabled = false) {
-        if (enabled) {
-            browser.webRequest.onHeadersReceived.addListener(
-                this._responseListener,
-                {
-                    urls: [
-                        "https://metager.org/*",
-                        "https://metager.de/*"
-                    ]
-                },
-                ["blocking", "responseHeaders"],
-            );
-        } else {
-            browser.webRequest.onHeadersReceived.removeListener(this._responseListener);
+        if (changes.hasOwnProperty("settings_settings")) {
+            this.settings = changes.settings_settings.newValue;
         }
     }
 
-    _handleRequestHeaders(details) {
+    handleRequestHeaders(details) {
+        if (!this.store_settings) return details.requestHeaders;
+        console.log("handle");
         let cookies = [];
 
         let headers = [];
@@ -95,14 +54,16 @@ export class SettingsManager {
             headers.push(cookie_header);
 
         }
-        return { requestHeaders: headers }
+        console.log(headers);
+        return headers;
     }
 
     /**
      * 
      * @param {*} details 
      */
-    _handleResponseHeaders(details) {
+    handleResponseHeaders(details) {
+        if (!this.store_settings) return details.responseHeaders;
         if (details.hasOwnProperty("responseHeaders")) {
             let new_headers = [];   // Cookie Array without set-cookie
             let settings_changed = false;
@@ -131,7 +92,7 @@ export class SettingsManager {
             if (settings_changed) {
                 browser.storage.sync.set({ settings_settings: this.settings });
             }
-            return { responseHeaders: new_headers };
+            return new_headers;
         }
     }
 }
\ No newline at end of file
diff --git a/build/js/app.js b/build/js/app.js
index a6c9060..47b6cdb 100644
--- a/build/js/app.js
+++ b/build/js/app.js
@@ -1,5 +1,52 @@
+const { Cookie } = require("./Cookie");
 const { SettingsManager } = require("./SettingsManager");
 
-(() => {
-    let settingsManager = new SettingsManager();
+(async () => {
+    let settingsManager = new SettingsManager()
+    await settingsManager.init();
+
+    // Handle existing cookies when enabling/disabling setting storage
+    browser.storage.onChanged.addListener(async (changes, areaName) => {
+        settingsManager.handleStorageChange(changes);
+        if (!browser.cookies) return;
+        if (changes.hasOwnProperty("settings_store")) {
+            let new_value = changes.settings_store.newValue;
+            if (new_value == true) {
+                // Setting storage now enabled
+                await Cookie.COOKIES_TO_SETTINGS();
+            } else if (new_value == false) {
+                // Setting storage now disabled. Put all settings into browser cookie storage
+                await Cookie.SETTINGS_TO_COOKIES()
+            }
+        }
+    });
+
+    // Handle Request Headers
+    browser.webRequest.onBeforeSendHeaders.addListener(
+        details => {
+            let headers = settingsManager.handleRequestHeaders(details);
+            return { requestHeaders: headers };
+        },
+        {
+            urls: [
+                "https://metager.org/*",
+                "https://metager.de/*"
+            ]
+        },
+        ["blocking", "requestHeaders"],
+    );
+    // Handle Response Headers
+    browser.webRequest.onHeadersReceived.addListener(
+        details => {
+            let headers = settingsManager.handleResponseHeaders(details);
+            return { responseHeaders: headers };
+        },
+        {
+            urls: [
+                "https://metager.org/*",
+                "https://metager.de/*"
+            ]
+        },
+        ["blocking", "responseHeaders"],
+    );
 })();
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index 3078455..63ae556 100644
--- a/manifest.json
+++ b/manifest.json
@@ -35,7 +35,8 @@
     "permissions": [
         "webRequest",
         "webRequestBlocking",
-        "storage"
+        "storage",
+        "cookies"
     ],
     "content_scripts": [
         {
@@ -57,6 +58,7 @@
         "webRequestBlocking"
     ],
     "background": {
+        "type": "module",
         "scripts": [
             "js/app.js"
         ]
diff --git a/web/settings/index.js b/web/settings/index.js
index bd24bef..d53ce05 100644
--- a/web/settings/index.js
+++ b/web/settings/index.js
@@ -30,7 +30,7 @@
     async function initializeSettingsState() {
         // Initialize stored settings
         let synced_settings = await browser.storage.sync.get({
-            settings_store: false,
+            settings_store: true,
         });
 
         if (synced_settings.settings_store == true) {
-- 
GitLab