Manually add a search engine to Firefox Quantum

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 be null 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, call getVerificationHash(loadPath) and the result is what you need in loadPathHash.
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!

コメントを残す