From fe45bbc8dc11f5dc815831ea6e9c69523fdd0028 Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Thu, 6 Apr 2023 10:49:21 +0000 Subject: [PATCH] Combine the CSS files on FF startup Instead of combining the CSS files during make, just install all of the fragments and let mobile-config-autoconfig.js combine them. --- Makefile | 32 +++++-- src/common/header.css | 8 +- src/mobile-config-autoconfig.js | 164 ++++++++++++++++++++++++-------- 3 files changed, 150 insertions(+), 54 deletions(-) diff --git a/Makefile b/Makefile index c54e28d..c7f2953 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Copyright 2022 Oliver Smith +# Copyright 2023 Oliver Smith # SPDX-License-Identifier: MPL-2.0 HEADER_FILE := src/common/header.css @@ -8,18 +8,22 @@ DESTDIR := FIREFOX_DIR := /usr/lib/firefox FIREFOX_CONFIG_DIR := /etc/firefox -all: out/userChrome.css out/userContent.css +all: out/userChrome.files out/userContent.files clean: rm -rf out out: mkdir out -out/userChrome.css: $(USERCHROME_FILES) out - cat $(USERCHROME_FILES) > $@ +out/userChrome.files: $(USERCHROME_FILES) out + for i in $(USERCHROME_FILES); do \ + echo "$$i" | cut -d/ -f 2-; \ + done > $@ -out/userContent.css: $(USERCONTENT_FILES) out - cat $(USERCONTENT_FILES) > $@ +out/userContent.files: $(USERCONTENT_FILES) out + for i in $(USERCONTENT_FILES); do \ + echo "$$i" | cut -d/ -f 2-; \ + done > $@ install: all install -Dm644 src/policies.json \ @@ -28,10 +32,18 @@ install: all "$(DESTDIR)/$(FIREFOX_DIR)/defaults/pref/mobile-config-prefs.js" install -Dm644 src/mobile-config-autoconfig.js \ "$(DESTDIR)/$(FIREFOX_DIR)/mobile-config-autoconfig.js" - install -Dm644 "out/userChrome.css" \ - "$(DESTDIR)/etc/mobile-config-firefox/userChrome.css" - install -Dm644 "out/userContent.css" \ - "$(DESTDIR)/etc/mobile-config-firefox/userContent.css" + install -Dm644 "out/userChrome.files" \ + -t "$(DESTDIR)/etc/mobile-config-firefox" + install -Dm644 "out/userContent.files" \ + -t "$(DESTDIR)/etc/mobile-config-firefox" + for dir in common userChrome userContent; do \ + for i in src/$$dir/*.css; do \ + install \ + -Dm644 \ + "$$i" \ + -t "$(DESTDIR)/etc/mobile-config-firefox/$$dir"; \ + done; \ + done install -Dm644 org.postmarketos.mobile_config_firefox.metainfo.xml \ "$(DESTDIR)/usr/share/metainfo/org.postmarketos.mobile_config_firefox.metainfo.xml" diff --git a/src/common/header.css b/src/common/header.css index 8060752..f564a11 100644 --- a/src/common/header.css +++ b/src/common/header.css @@ -1,4 +1,4 @@ -/* Copyright 2022 Oliver Smith, Arnaud Ferraris +/* Copyright 2023 Oliver Smith, Arnaud Ferraris * SPDX-License-Identifier: MPL-2.0 * _ _ _ __ _ * _ __ ___ ___ | |__ (_) | ___ ___ ___ _ __ / _(_) __ _ @@ -10,9 +10,9 @@ * * WARNING: DO NOT EDIT THE COPY OF THIS FILE LOCATED IN YOUR USER PROFILE! * - * It will be overwritten on upgrade. You should edit the file located in + * It will be overwritten on upgrade. You should edit the files located in * /etc/mobile-config-firefox/ instead (most package managers won't replace * files under /etc if they've been edited). Or alternatively, consider cloning - * mobile-config-firefox.git and editing the separate CSS files there, then - * combining them with "make". Patches for useful additions welcome! + * mobile-config-firefox.git and editing the separate CSS files there. + * Patches for useful additions welcome! */ diff --git a/src/mobile-config-autoconfig.js b/src/mobile-config-autoconfig.js index b59def7..6969800 100644 --- a/src/mobile-config-autoconfig.js +++ b/src/mobile-config-autoconfig.js @@ -10,6 +10,7 @@ Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/FileUtils.jsm"); var updated = false; +var fragments_cache = {}; // cache for css_file_get_fragments() // Create /chrome/ directory if not already present var chromeDir = Services.dirsvc.get("ProfD", Ci.nsIFile); @@ -81,48 +82,131 @@ function set_default_prefs() { defaultPref('browser.newtabpage.enabled', true); } +// Get an array of paths to the fragments for one CSS file +// name: either "userChrome" or "userContent" +function css_file_get_fragments(name) { + if (name in fragments_cache) + return fragments_cache[name]; + + var ret = []; + var path = "/etc/mobile-config-firefox/" + name + ".files"; + log("Reading fragments from file: " + path); + var file = new FileUtils.File(path); + + var istream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Components.interfaces.nsIFileInputStream); + istream.init(file, 0x01, 0444, 0); + istream.QueryInterface(Components.interfaces.nsILineInputStream); + + var has_more; + do { + var line = {}; + has_more = istream.readLine(line); + ret.push("/etc/mobile-config-firefox/" + line.value); + } while (has_more); + + istream.close(); + + fragments_cache[name] = ret; + return ret; +} + +// Create a nsIFile object with one of the CSS files in the user's profile as +// path. The file doesn't need to exist at this point. +// name: either "userChrome" or "userContent" +function css_file_get(name) { + var ret = chromeDir.clone(); + ret.append(name + ".css"); + return ret; +} + +// Delete either userChrome.css or userContent.css inside the user's profile if +// they have an older timestamp than the CSS fragments (or list of CSS +// fragments) installed system-wide. +// name: either "userChrome" or "userContent" +// file: return of css_file_get() +function css_file_delete_outdated(name, file) { + var depends = css_file_get_fragments(name).slice(); /* copy the array */ + depends.push("/etc/mobile-config-firefox/" + name + ".files"); + for (var i in depends) { + var depend = depends[i]; + var file_depend = new FileUtils.File(depend); + + if (file.lastModifiedTime < file_depend.lastModifiedTime) { + log("Removing outdated file: " + file.path + " (newer: " + + depend + ")"); + file.remove(false); + return; + } + } + + log("File is up-to-date: " + file.path); + return; +} + +// Create userChrome.css / userContent.css in the user's profile, based on the +// CSS fragments stored in /etc/mobile-config-firefox. +// name: either "userChrome" or "userContent" +// file: return of css_file_get() +function css_file_merge(name, file) { + log("Creating CSS file from fragments: " + file.path); + + var ostream = Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(Components.interfaces.nsIFileOutputStream); + ostream.init(file, 0x02 | 0x08 | 0x20, 0644, 0); + + var fragments = css_file_get_fragments(name); + for (var i in fragments) { + var line; + var fragment = fragments[i]; + log("- " + fragment); + line = "/* === " + fragment + " === */\n" + ostream.write(line, line.length); + + var file_fragment = new FileUtils.File(fragment); + + var istream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Components.interfaces.nsIFileInputStream); + istream.init(file_fragment, 0x01, 0444, 0); + istream.QueryInterface(Components.interfaces.nsILineInputStream); + + var has_more; + do { + var line = {}; + has_more = istream.readLine(line); + line = line.value + "\n"; + ostream.write(line, line.length); + } while (has_more); + + istream.close(); + } + + ostream.close(); + updated = true; +} + +function css_files_update() { + var ff_version = get_firefox_version(); + log("Firefox version: " + ff_version); + + var names = ["userChrome", "userContent"]; + for (var i in names) { + var name = names[i]; + var file = css_file_get(name); + + if (file.exists()) { + css_file_delete_outdated(name, file); + } + + if (!file.exists()) { + css_file_merge(name, file); + } + } +} + log("Running mobile-config-autoconfig.js"); -var ff_version = get_firefox_version(); -log("Firefox version: " + ff_version); - -// Create nsIFile objects for userChrome.css in /chrome/ and in /etc/ -var chromeFile = chromeDir.clone(); -chromeFile.append("userChrome.css"); -var defaultChrome = new FileUtils.File("/etc/mobile-config-firefox/userChrome.css"); - -// Remove the existing userChrome.css if older than the installed one -if (chromeFile.exists() && defaultChrome.exists() && - chromeFile.lastModifiedTime < defaultChrome.lastModifiedTime) { - log("Removing outdated userChrome.css from profile"); - chromeFile.remove(false); -} - -// Copy userChrome.css to /chrome/ -if (!chromeFile.exists()) { - log("Copying userChrome.css from /etc/mobile-config-firefox to profile"); - defaultChrome.copyTo(chromeDir, "userChrome.css"); - updated = true; -} - -// Create nsIFile objects for userContent.css in /chrome/ and in /etc/ -var contentFile = chromeDir.clone(); -contentFile.append("userContent.css"); -var defaultContent = new FileUtils.File("/etc/mobile-config-firefox/userContent.css"); - -// Remove the existing userContent.css if older than the installed one -if (contentFile.exists() && defaultContent.exists() && - contentFile.lastModifiedTime < defaultContent.lastModifiedTime) { - log("Removing outdated userContent.css from profile"); - contentFile.remove(false); -} - -// Copy userContent.css to /chrome/ -if (!contentFile.exists()) { - log("Copying userContent.css from /etc/mobile-config-firefox to profile"); - defaultContent.copyTo(chromeDir, "userContent.css"); - updated = true; -} +css_files_update(); // Restart Firefox immediately if one of the files got updated if (updated == true)