Firefox#

Disable search in address bar#

These settings disable search engine queries in the search bar.

See also

  • I want to disable search in the address bar and browser.urlbar.unifiedcomplete is not an option anymore | Firefox Support Forum | Mozilla Support [1]

  1. open Firefox

  2. open about:config in the address bar

  3. Set these values to false

    keyword.enabled                     false
    browser.fixup.alternate.enabled     false
    

Profiles#

You can handle multiple Firefox profiles in separate sandboxes with this script

See also

  • A collection of scripts I have written and/or adapted that I currently use on my systems as automated tasks [2]

  • GitHub - netblue30/firejail: Linux namespaces and seccomp-bpf sandbox [3]

  1. install the dependencies

    apt-get install firejail/bullseye-backports yad python3-yaml firefox-esr
    

    Note

    You need to enable the backports before installing firejail. The upstream repository recommends this version for Debian.

  2. install fpyutils. See reference

  3. create the jobs directories. See reference

    mkdir -p /home/jobs/scripts/by-user/myuser
    chown -R myuser:myuser /home/jobs/scripts/by-user/myuser
    chmod 700 -R /home/jobs/scripts/by-user/myuser
    usermod -aG jobs myuser
    
  4. create the script

    /home/jobs/scripts/myuser/firefox_profile_runner.py#
    #!/usr/bin/env python3
    #
    # firefox_profile_runner.py
    #
    # Copyright (C) 2021-2022 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com)
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program.  If not, see <http://www.gnu.org/licenses/>.
    #
    #
    r"""A menu to run different Firefox profiles in sandboxes."""
    
    import copy
    import os
    import shlex
    import shutil
    import sys
    
    import fpyutils
    import yaml
    from yad import YAD
    
    
    def ask_profile_question(profile_names: list, type: str, yad) -> str:
        prf: str
        profiles: list = copy.deepcopy(profile_names)
        profiles.sort()
        data: list = profiles
        text: str = 'Select a profile'
        window_title: str = 'Firefox profile selection'
        width: int = 640
        height: int = 480
        profile: str = None
    
        if type == 'entry':
            profile = yad.Entry(
                label=text,
                title=window_title,
                width=width,
                height=height,
                fixed=True,
                center=True,
                quoted=True,
                no_markup=True,
                use_completion='true',
                data=data,
            )
        elif type == 'list':
            data = [[x] for x in data]
            profile = yad.List(
                text=text,
                title=window_title,
                width=width,
                height=height,
                fixed=True,
                center=True,
                colnames=[('profile', 'TEXT')],
                quoted=True,
                no_markup=True,
                data=data,
            )
    
        if profile is None:
            sys.exit(0)
        else:
            if type == 'entry':
                prf = profile
            else:
                prf = profile[0]
    
        return prf
    
    
    def build_command(profile: dict, firefox_executable: str,
                      firejail_executable: str) -> str:
        command = ''
    
        firefox_command = firefox_executable + ' -P ' + shlex.quote(
            profile['firefox']['profile_name'])
        for o in profile['firefox']['options']:
            firefox_command += ' ' + shlex.quote(o)
    
        if profile['firejail']['enabled']:
    
            firejail_command = firejail_executable
    
            for o in profile['firejail']['options']:
                firejail_command += ' ' + shlex.quote(o)
    
            command = firejail_command + ' ' + firefox_command
    
        else:
            command += firefox_command
    
        return command
    
    
    def show_configuration_error(error: str, yad):
        message = 'Check configuration or arguments'
        yad.execute(args=[
            '--title="Configuration error"', '--width=640', '--height=480',
            '--text="' + message + '\n\n' + repr(error) +
            '"', '--button="Ok:0"', '--no-markup'
        ])
    
    
    def show_profile_message(profile: str, sandbox_enabled: bool, load: bool, yad):
        sandbox_status = 'disabled'
        if sandbox_enabled:
            sandbox_status = 'enabled'
    
        if load:
            message = 'Loading profile **' + profile + '** with sandbox **' + sandbox_status + '**. Please wait...'
            title = 'Loading Firefox profile'
        else:
            message = 'Quit profile **' + profile + '** with sandbox **' + sandbox_status + '**.'
            title = 'Exited from Firefox profile'
    
        yad.execute(args=[
            '--title="' + title + '"', '--width=640', '--height=480', '--text="' +
            message + '"', '--timeout=5', '--timeout-indicator=bottom',
            '--button="Ok:0"', '--no-markup'
        ])
    
    
    def binaries_exist(binaries: dict) -> bool:
        binaries_present = False
        if (shutil.which(binaries['firefox']) is not None
                and shutil.which(binaries['firejail']) is not None):
            binaries_present = True
    
        return binaries_present
    
    
    def check_configuration_structure(configuration: dict) -> bool:
        ok = True
        if ('binaries' in configuration and 'firefox' in configuration['binaries']
                and 'firejail' in configuration['binaries']
                and isinstance(configuration['binaries']['firefox'], str)
                and isinstance(configuration['binaries']['firejail'], str)):
            ok = True
        else:
            ok = False
        if (ok and 'message' in configuration
                and 'start' in configuration['message']
                and 'end' in configuration['message']
                and 'errors' in configuration['message']
                and isinstance(configuration['message']['start'], bool)
                and isinstance(configuration['message']['end'], bool)
                and isinstance(configuration['message']['errors'], bool)):
            ok = True
        else:
            ok = False
        if (ok and 'profile_list_type' in configuration
                and isinstance(configuration['profile_list_type'], str)
                and configuration['profile_list_type'] in ['entry', 'list']):
            ok = True
        else:
            ok = False
        if (ok and 'profiles' in configuration
                and isinstance(configuration['profiles'], dict)):
    
            # At least one profile must be present.
            if len(configuration['profiles']) <= 0:
                ok = False
            else:
                profiles = configuration['profiles']
                profiles_keys = list(profiles.keys())
    
                i = 0
                while ok and i < len(profiles_keys):
                    prf = profiles[profiles_keys[i]]
    
                    if not isinstance(prf, dict):
                        ok = ok & False
    
                    if (ok and 'firefox' in prf and 'firejail' in prf
                            and 'profile_name' in prf['firefox']
                            and isinstance(prf['firefox']['profile_name'], str)
                            and 'options' in prf['firefox']
                            and isinstance(prf['firefox']['options'], list)
                            and 'enabled' in prf['firejail']
                            and isinstance(prf['firejail']['enabled'], bool)
                            and 'options' in prf['firejail']
                            and isinstance(prf['firejail']['options'], list)):
                        ok = ok & True
    
                        j = 0
                        options = prf['firefox']['options']
                        while ok and j < len(options):
                            if isinstance(options[j], str):
                                ok = ok & True
                            else:
                                ok = ok & False
                            j += 1
    
                        j = 0
                        options = prf['firejail']['options']
                        while ok and j < len(options):
                            if isinstance(options[j], str):
                                ok = ok & True
                            else:
                                ok = ok & False
                            j += 1
                    else:
                        ok = ok & False
    
                    i += 1
        else:
            ok = False
    
        return ok
    
    
    if __name__ == '__main__':
    
        def main():
            yad = YAD()
    
            try:
                configuration_file = shlex.quote(sys.argv[1])
                try:
                    config = yaml.load(open(configuration_file),
                                       Loader=yaml.SafeLoader)
                except yaml.parser.ParserError as e:
                    show_configuration_error(str(e), yad)
                    sys.exit(1)
    
                if not check_configuration_structure(config):
                    raise ValueError
                if not binaries_exist(config['binaries']):
                    raise FileNotFoundError
            except (IndexError, FileNotFoundError, ValueError) as e:
                if config['message']['errors']:
                    show_configuration_error(str(e), yad)
                sys.exit(1)
    
            profile = ask_profile_question(list(config['profiles'].keys()),
                                           config['profile_list_type'], yad)
            command = build_command(config['profiles'][profile],
                                    config['binaries']['firefox'],
                                    config['binaries']['firejail'])
    
            pid = os.fork()
            if pid > 0:
                if config['message']['start']:
                    show_profile_message(
                        profile,
                        config['profiles'][profile]['firejail']['enabled'], True,
                        yad)
            else:
                r = fpyutils.shell.execute_command_live_output(command)
                if config['message']['errors'] and r != 0:
                    show_configuration_error('error: returned ' + str(r), yad)
                elif config['message']['end']:
                    show_profile_message(
                        profile,
                        config['profiles'][profile]['firejail']['enabled'], False,
                        yad)
            try:
                pid, status = os.waitpid(pid, 0)
            except ChildProcessError as e:
                print(e)
                sys.exit(1)
    
        main()
    
  5. import the configuration file

    /home/jobs/scripts/myuser/firefox_profile_runner.yaml#
    #
    # firefox_profile_runner.yaml
    #
    # Copyright (C) 2021-2022 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com)
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program.  If not, see <https://www.gnu.org/licenses/>.
    
    binaries:
        firefox: '/usr/bin/firefox-esr'
        firejail: '/usr/bin/firejail'
    
    # Show starting, quitting and error messages for each profile.
    message:
        start: true
        end: true
        errors: true
    
    # Possible values: 'entry', 'list'
    profile_list_type: 'list'
    
    profiles:
        personal:
            firefox:
                profile_name: 'personal'
                options: []
            firejail:
                enabled: true
                options:
                - '--apparmor'
    
                # IMPORTANT: this directory must exist prior running the scipt.
                - '--private=/home/myuser/firefox-firejail/personal'
    
                - '--private-cache'
                - '--private-dev'
                - '--private-tmp'
                - '--disable-mnt'
        internal:
            firefox:
                profile_name: 'internal'
                options: []
            firejail:
                enabled: true
                options:
                - '--apparmor'
                - '--private-cache'
                - '--private-dev'
                - '--private-tmp'
                - '--disable-mnt'
        isolated:
            firefox:
                profile_name: 'isolated'
                options: []
            firejail:
                enabled: true
                options:
                - '--whitelist=~/my_network_files'
                - '--nosound'
                - '--net=none'
        work:
            firefox:
                profile_name: 'work'
                options: []
            firejail:
                enabled: true
                options:
                - '--apparmor'
                - '--private=/home/myuser/firefox-firejail/work'
                - '--private-cache'
                - '--private-dev'
                - '--private-tmp'
                - '--disable-mnt'
        shopping:
            firefox:
                profile_name: 'shopping'
                options: []
            firejail:
                enabled: true
                options:
                - '--apparmor'
                - '--nosound'
                - '--dns=8.8.8.8'
                - '--private=/home/myuser/firefox-firejail/shopping'
                - '--private-cache'
                - '--private-dev'
                - '--private-tmp'
                - '--disable-mnt'
        cryptocurrencies:
            firefox:
                profile_name: 'cryptocurrencies'
                options: []
            firejail:
                enabled: true
                options:
                - '--apparmor'
                - '--nosound'
                - '--dns=8.8.8.8'
                - '--private=/home/myuser/firefox-firejail/cryptocurrencies'
                - '--private-cache'
                - '--private-dev'
                - '--private-tmp'
                - '--disable-mnt'
    
  6. if your configuration uses private home directories through the --private= option you must create them before running the script

  7. go back to your regular desktop user

    exit
    
  8. install python-yad

    pip3 install --user yad
    
  9. run the script

    pushd /home/jobs/scripts/by-user/myuser && ./firefox_profile_runner.py ./firefox_profile_runner.yaml && popd
    

    Note

    You can create, for example, a launcher on your desktop or a key combination to launch the script. This is what I use in my specrtwm configuration

    program[firefox]     = bash -c "pushd /home/jobs/scripts/by-user/myuser && ./firefox_profile_runner.py ./firefox_profile_runner.yaml 1>/dev/null 2>/dev/null &" 1/dev/null 2>/dev/null'
    bind[firefox]        = MOD+i
    

Block all domains except one#

If you use Firefox profiles for different purposes you might need to block some domains. I use this for example for my Gitea Firefox profile: when Gitea renders a markdown file, and there are images hosted on external websites, you can block them like this:

  1. open Firefox

  2. install the uBlock Origin extension

  3. go into uBlock Origin’s settings and open the My Filters section

  4. add this content

    https://*.*
    http://*.*
    @@||my.domain.org
    

    where my.domain.org is the whitelisted domain

Disable all images#

Set permissions.default.images = 2 in about:config

Footnotes