Background
I would like to add crates.io to Firefox Quantum but got an error saying that it cannot add it via https://crates.io/opensearch.xml
So here comes a short note of manually adding a search engine to Firefox Quantum.
Step 1: Extract search.json.mozlz4
Definitions of installed search engines are stored in the file search.json.mozlz4
which is located in your profile folder. Under Linux it’s usually ~/.mozilla/firefox/XXXXXXXX.default
. If you’re unsure about it, run firefox -profilemanager
(or firefox-developer-edition -profilemanager
) to find it out.
To decompress this file, a small Python script MozLz4a compression/decompression utility can do us a favour. Note that as mentioned in the comments, you may need to modify the script a little since Python lz4
has updated its API.
$ python mozlz4a.py -d search.json.mozlz4 search.json $ cat search.json | json_reformat | tee search.json
Step 2: Add the definition of your search engine
Add a new object to the engines
array. Here’s the one for GitHub. Modify it as per the configuration of yours.
{ "_name": "GitHub", "_shortName": "github", "_loadPath": "[https]github.com/github.xml", "description": "Search GitHub", "__searchForm": "https://github.com/search", "_iconURL": "data:image/x-icon;base64,XXXXX", "_metaData": { "loadPathHash": "KMHVysvC2OH4i+7/Ay7hqZvgIBBe8rgxAnMjNkVslos=", "order": 11, "alias": "git" }, "_urls": [ { "template": "https://github.com/search?q={searchTerms}&ref=opensearch", "rels": [], "resultDomain": "github.com", "params": [] } ], "queryCharset": "UTF-8", "_readOnly": false }
__searchForm
can benull
if not needed.- Image to data-URI converter can help you with the
_iconURL
field. - The hash function for
loadPathHash
can be found in Mozilla’s source code. I have copied it here for your convenience. Open a Browser Console in Firefox, paste the following function, callgetVerificationHash(loadPath)
and the result is what you need inloadPathHash
.
function getVerificationHash(aName) { let disclaimer = "By modifying this file, I agree that I am doing so " + "only within $appName itself, using official, user-driven search " + "engine selection processes, and in a way which does not circumvent " + "user consent. I acknowledge that any attempt to change this file " + "from outside of $appName is a malicious act, and will be responded " + "to accordingly." let salt = OS.Path.basename(OS.Constants.Path.profileDir) + aName + disclaimer.replace(/\$appName/g, Services.appinfo.name); let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] .createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = "UTF-8"; // Data is an array of bytes. let data = converter.convertToByteArray(salt, {}); let hasher = Cc["@mozilla.org/security/hash;1"] .createInstance(Ci.nsICryptoHash); hasher.init(hasher.SHA256); hasher.update(data, data.length); return hasher.finish(true); }
Step 3: Replace the original file
Make sure that you’ve closed Firefox entirely and take a backup of the original search.json.mozlz4
file.
$ mv search.json.mozlz4 search.json.mozlz4.bak $ python mozlz4a.py search.json search.json.mozlz4
Then… Done! Yay!