Search code examples
linuxfirefoxterminalfirefox-addonxpi

Arch Linux - How to install Firefox extensions (with no install.rdf file) silenty by command line


I'm working on Arch Linux OS where I use Firefox 91.10.0esr (so, Firefox ESR) and I'm looking for a way to install silently Firefox addons by using terminal. I'm aware of methods to install them by calling the downloaded addon .xpi as firefox-esr <addon-name>.xpi but it opens Firefox and asks for a further confirmation of the installation.

My purpose is to perform the installation of the .xpi file only by command line without interact with the browser GUI and avoid the further install confirmation (the "Add" button on the popup opened by the browser).

According to several sources (i.e., https://askubuntu.com/questions/73474/how-to-install-firefox-addon-from-command-line-in-scripts) where the process is explained for addons that contain install.rdf file, it is easy to manage this case.

My issue is related to those .xpi files that don't include a install.rdf file containing the ID of the application.

For example, if we consider FoxyProxy addon and we download it and extract it:

mkdir foxyproxy && cd foxyproxy
wget https://addons.mozilla.org/firefox/downloads/file/3611407/foxyproxy_standard-7.5.1.xpi
unzip foxyproxy_standard-7.5.1.xpi

among the extracted files, there is not a install.rdf file containing the usual hexadecimal ID of the extension. The only ID I can see is inside the manifest.json file that does not have the hexadecimal format. Taking for example FoxyProxy, I tried to use its ID [email protected] by making the process like:

mkdir -p /usr/share/mozilla/extensions/[email protected]

or

mkdir -p /home/user/.mozilla/extensions/[email protected]

and then copy all the unzipped content of.xpi in one of these directories, but with no luck.

Is it possible to install by CLI this kind of addons with no install.rdf file?


Solution

  • TL;DR

    Run this config_firefox.sh script:

    #!/bin/bash
    sudo mkdir -p /etc/firefox/policies
    sudo cp policies.json /etc/firefox/policies/policies.json
    
    

    Which copies (the following policies.json file that you have to put in the same folder as the config_firefox.sh script):

    {
      "policies": {
        "Extensions": {
          "Install": [
            "https://addons.mozilla.org/firefox/downloads/file/3551054/ublock_origin-latest.xpi"
          ]
        },
        "ExtensionUpdate": true,
        "DisableTelemetry": true,
        "DisableFirefoxStudies": true,
        "EnableTrackingProtection": {
          "Value": true,
          "Locked": false,
          "Cryptomining": true,
          "Fingerprinting": true,
          "EmailTracking": true,
          "Exceptions": []
        }
      }
    }
    
    

    into: `/etc/firefox/policies/policies.json and restart Firefox. (You don't have to click "accept" anything anymore, they are automatically installed.

    Answers XY-problem of question, doesn't work:

    This script gets the extension ID from the manifest.json files inside the .xpi files: (However, Firefox does not automatically install the .xpi files if I export them to: /home/<username>/snap/firefox/common/.mozilla/firefox/<profilename>.default/extensions.

    #!/bin/bash
    
    # Constants
    #FIREFOX_PATH=~/.mozilla/firefox
    FIREFOX_PATH=~/snap/firefox/common/.mozilla/firefox/
    echo "FIREFOX_PATH=$FIREFOX_PATH"
    FIREFOX_PROFILE=$(cat ${FIREFOX_PATH}/profiles.ini | grep "Path=" | cut -d= -f2)
    echo "FIREFOX_PROFILE=$FIREFOX_PROFILE"
    FIREFOX_PROFILE_PATH=${FIREFOX_PATH}/${FIREFOX_PROFILE}
    #read -p "FIREFOX_PROFILE_PATH=$FIREFOX_PROFILE_PATH"
    FIREFOX_EXT_PATH=${FIREFOX_PROFILE_PATH}/extensions
    #FIREFOX_EXT_PATH=${FIREFOX_PATH}/extensions
    echo "FIREFOX_EXT_PATH=$FIREFOX_EXT_PATH"
    mkdir -p "$FIREFOX_EXT_PATH"
    
    install_firefox_extensions () {
        echo  ">>> Installing Firefox extensions ..."
        mkdir -p /tmp/firefox-install-extensions
        cd /tmp/firefox-install-extensions
    
        install_extension "uBlock"\
            https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/addon-607454-latest.xpi
        exit 5
        install_extension "uMatrix"\
            https://addons.mozilla.org/firefox/downloads/latest/umatrix/addon-613250-latest.xpi
        install_extension "Vimperator"\
            https://addons.mozilla.org/firefox/downloads/file/450078/vimperator-latest-fx.xpi
        install_extension "Tab Groups"\
            https://addons.mozilla.org/firefox/downloads/latest/tab-groups-panorama/addon-671381-latest.xpi
        install_extension "Cookies Manager+"\
            https://addons.mozilla.org/firefox/downloads/latest/cookies-manager-plus/addon-92079-latest.xpi
        rm -rf /tmp/firefox-install-extensions
    }
    
    
    get_rhs_of_line_till_character() {
        local line=$1
        local character=$2
        
        rhs=$(cut -d "$character" -f2- <<< "$line")
        echo "$rhs"
    }
    
    get_extension_id(){
        local keyword="$1"
        
        local ext_uid=$(unzip -p addon.xpi manifest.json | grep "$keyword" | head -n 1)
        
        # If not is None, get everything after:'"id": "' and drop last quotation and comma.
        if [ "$ext_uid" != "" ]; then
            local first_cut=$(get_rhs_of_line_till_character "$ext_uid" ":")
            #echo "first_cut=$first_cut"
            local second_cut=$(get_rhs_of_line_till_character "$first_cut" '"')
            #echo "second_cut=$second_cut"
            local trim_tail=${second_cut::-2}
            #echo "trim_tail=$trim_tail"
            echo "$trim_tail"
        fi
    }
    
    manual_assert_file_exists() {
        local filepath="$1"
        if [ ! -f "$filepath" ]; then
            echo "The file: $filepath does not exist."
            exit 29
        fi
    }
    
    install_extension () {
        local ext_name=$1
        local ext_url=$2
    
        echo ">>> Installing ${ext_name} ..."
    
        rm addon.xpi
        wget --quiet -O addon.xpi "${ext_url}"
        STATUS=$?
        if [ $STATUS -ne 0 ]; then
            echo ">>>> error downloading $ext_name"
        fi
        manual_assert_file_exists "addon.xpi"
    
        
        local xpi_id=$(get_extension_id "id")
        if [ "$xpi_id" == "" ]; then
            xpi_id=$(get_extension_id "short_name")
        fi
        if [ "$xpi_id" == "" ]; then
            echo "Error, did not find xpi-id for:$ext_name"
        fi
        echo "xpi_id=$xpi_id"
    
        cp -f addon.xpi "${FIREFOX_EXT_PATH}/${xpi_id}.xpi"
        unzip addon.xpi -d "${FIREFOX_EXT_PATH}/${xpi_id}"
    }
    
    install_firefox_extensions
    
    
    #echo ">>>> changing default search to DuckDuckGo"
    #while [ ! -f "$FIREFOX_PROFILE/search.json.mozlz4" ]
    #do
    #   echo ">>>> waiting for search.json.mozlz4 to be created..."
    #   sleep 1
    #done