summaryrefslogtreecommitdiff
path: root/legacy/LegacyFoxUtils.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'legacy/LegacyFoxUtils.sys.mjs')
-rw-r--r--legacy/LegacyFoxUtils.sys.mjs83
1 files changed, 83 insertions, 0 deletions
diff --git a/legacy/LegacyFoxUtils.sys.mjs b/legacy/LegacyFoxUtils.sys.mjs
new file mode 100644
index 0000000..6d13c2c
--- /dev/null
+++ b/legacy/LegacyFoxUtils.sys.mjs
@@ -0,0 +1,83 @@
+/**
+ * Replacements for Components.manager.addBootstrappedManifestLocation and
+ * Components.manager.removeBootstrappedManifestLocation, which have been nixed
+ * in mozilla142. Copyright 2025 Tobias Girstmair <https://gir.st/>, MPLv2.
+ */
+var LegacyFoxUtils = (function() {
+const ZipReader = Components.Constructor(
+ "@mozilla.org/libjar/zip-reader;1",
+ "nsIZipReader",
+ "open"
+);
+
+const ScriptableInputStream = Components.Constructor(
+ "@mozilla.org/scriptableinputstream;1",
+ "nsIScriptableInputStream",
+ "init"
+);
+
+const FileOutputStream = Components.Constructor(
+ "@mozilla.org/network/file-output-stream;1",
+ "nsIFileOutputStream",
+ "init"
+);
+
+return class LegacyFoxUtils {
+ static addBootstrappedManifestLocation(file, addon, uriMaker) {
+ // read chrome.manifest from .jar (or unpacked addon)
+ let zipReader = new ZipReader(file);
+ let istream = new ScriptableInputStream(zipReader.getInputStream("chrome.manifest"));
+ let manifestContents = istream.read(zipReader.getEntry("chrome.manifest").realSize);
+
+ // replace chrome:// and resource:// URIs with absolute paths to JAR
+ manifestContents = manifestContents
+ .split("\n")
+ .map(absolutizePaths.bind(null, uriMaker, file))
+ .join("\n");
+
+ // we store the temporary file in the user's profile, in a subdirectory
+ // analogous to webExtension's "browser-extension-data".
+ let manifest = Services.dirsvc.get('ProfD', Ci.nsIFile)
+ manifest.append('legacy-extension-data');
+ manifest.append(addon.id);
+ manifest.exists() || manifest.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
+ manifest.append('chrome.manifest'); /* created or truncated by ostream */
+
+ // write modified chrome.manifest to profile directory
+ let ostream = new FileOutputStream(manifest, -1, -1, 0);
+ ostream.write(manifestContents, manifestContents.length);
+ ostream.close();
+
+ // let Firefox read and parse it
+ Components.manager.QueryInterface(Ci.nsIComponentRegistrar).autoRegister(manifest);
+ }
+
+ static removeBootstrappedManifestLocation(addon) {
+ let manifestDir = Services.dirsvc.get('ProfD', Ci.nsIFile)
+ manifestDir.append('legacy-extension-data');
+ manifestDir.append(addon.id);
+ manifestDir.exists() && manifestDir.remove(/*recursive=*/true);
+ Cc['@mozilla.org/chrome/chrome-registry;1']
+ .getService(Ci.nsIXULChromeRegistry).checkForNewChrome();
+ }
+}
+
+function absolutizePaths(uriMaker, file, line) {
+ const manifestMethodPathLocation = {
+ content: 2, // content packagename uri/to/files/ [flags]
+ locale: 3, // locale packagename localename uri/to/files/ [flags]
+ skin: 3, // skin packagename skinname uri/to/files/ [flags]
+ resource: 2 // resource aliasname uri/to/files/ [flags]
+ };
+
+ let words = line.trim().split(/\s+/);
+ const index = manifestMethodPathLocation[words[0]];
+
+ if (index) {
+ words[index] = uriMaker(file, words[index]).spec;
+ line = words.join(" ");
+ }
+
+ return line;
+}
+})()