Go back to NOT selecting the whole URL when I click the address bar

Firefox, March 2020 and later

Around March 2020, the browser.urlbar.clickSelectsAll preference has been removed. Since then, this bug has been under discussion, where a patch has been suggested — this would involve recompiling Firefox from scratch.

As the clickSelectsAll doesn’t work” duplicates accumulate on Bugzilla, one of these has received a comment by Stephen McCarthy which describes a workaround that involves editing internal Firefox files, specifically the omni.ja which basically is a zip file that contains lots of internal files, e.g. JavaScript modules for the browser chrome, including the relevant modules/UrlbarInput.jsm. This workaround looks like the simplest approach, but the approach doesn’t work as-is.

There is an official documentation on MDN that describes how omni.ja should be repackaged. I also found a blog article on Shallow Thoughts about modifying omni.ja that describes this process in more detail. Then, there is another thing to worry about: you need to force Firefox to use the modified omni.ja by clearing its startup cache, which is explained in an In Pursuit Of Laziness blog article that I found.

Modifying internal files

Puttng all these resources together, these are the shell commands that currently work on Arch Linux (core/linux 5.8.1.arch1-1 through 5.12.13.arch1-2) with either Firefox Nightly 81.0a1 (2020-08-20) through 91.0a1 (2021-07-02) (64-bit) or Firefox ESR 78 (64-bit) (probably).1 If at any point you run into “permission denied” errors, simply continue executing the commands as root. These need to be executed after every Firefox update. The commands are explained afterwards.

Instead of typing the individual commands, you can use this shell script instead, available on this GitHub repo of mine. That script offers a user-friendly terminal interface; it automatically finds Firefox, changes the omni.ja and handles the cache. It also automatically switches to root as needed and creates backups.

The commands

cd /tmp
mkdir omni
unzip -d omni -q /usr/lib/firefox/browser/omni.ja
sed -i 's/this\._preventClickSelectsAll = this\.focused;/this._preventClickSelectsAll = true;/' omni/modules/UrlbarInput.jsm
sed -i 's/this\._preventClickSelectsAll = this\._textbox\.focused;/this._preventClickSelectsAll = true;/' omni/chrome/browser/content/browser/search/searchbar.js
cd omni
zip -0DXqr omni.ja *
cd ..
mv omni/omni.ja /usr/lib/firefox/browser/omni.ja
chown ⟨user⟩:⟨group⟩ /usr/lib/firefox/browser/omni.ja
rm -r omni

Important notes:

  • Update Firefox and then close it before doing this. Firefox needs to have the updates installed (i.e. you may have to start Firefox after upgrading, then close it again).

  • /usr/lib/firefox is a possible install path for Firefox; your path may differ, e.g. it may be /usr/share/firefox. You should be able to find the possible paths with one of these commands:

    whereis -b firefox firefox-esr
    which firefox firefox-esr
    

    The correct omni.ja is in the …/browser/omni.ja path.

  • Before any of this is executed make sure you create a copy of the working omni.ja somewhere, so you have a backup available in case something goes wrong.

  • Make sure you replace ⟨user⟩ by the user name and ⟨group⟩ by the user group of the original ownership of the file. As far as I know, in most cases, this should be root:root, if it isn’t already.

  • After unzipping omni.ja you may want to double check that

    • the line this._preventClickSelectsAll = this.focused; exists in modules/UrlbarInput.jsm, and
    • the line this._preventClickSelectsAll = this._textbox.focused; exists in chrome/browser/content/browser/search/searchbar.js.

Clearing the cache

Finally, Firefox needs to properly load the new omni.ja by purging the cache. These are the two different options I found easiest. Only one of the options is necessary.

  • One way to do that is to simply create an empty file named .purgecaches in the browser directory. For example, you can execute this:

    touch /usr/lib/firefox/browser/.purgecaches
    

    You’ll only need to create that file after running the above commands. On startup, Firefox will clear its startup cache if it finds this file, and it will also attempt to remove the file. Depending on how you originally installed Firefox, removing the file automatically may fail. Even if that doesn’t affect successfully clearing the cache, just be aware of that.

  • An alternative way is to find the desktop configuration file for Firefox. Look into /usr/share/applications/ or ~/.local/share/applications/ and find some *.desktop file with firefox (or nightly or maybe mozilla or something similar) in the file name. Open the files you found. On my system there are two of them:

    • A small one that starts firefox-bin (via Exec=)
    • A large one that has three references to /usr/lib/firefox/firefox

    You want to modify the larger one: after each /usr/lib/firefox/firefox (or whichever path it is for you) put the -purgecaches option (--purgecaches works, too); so one of the configuration entries may looke like this:

    Exec=/usr/lib/firefox/firefox -purgecaches %u
    

    Using this approach, you may need to edit your *.desktop file after every Firefox update and it slows down every start-up of Firefox.

Now you can start Firefox by clicking on the desktop icon.

There are two other alternatives, if you don’t start Firefox from clicking on the desktop icon, but instead use the terminal:

  • You can type firefox -purgecaches into the terminal,
  • or you can type export MOZ_PURGE_CACHES=1 into the terminal, then type firefox into the same terminal.

And finally, you can clear the cache directly, as well. The script caches, including the startup cache, are hidden in the .cache directory of your /home. The path will look something like /home/⟨user⟩/.cache/mozilla/firefox/⟨profileID⟩.⟨profileType⟩/startupCache. Deleting these directories will clear the startup cache of Firefox.

Use this approach if you use more than one profile on the same Firefox installation. The other built-in purgecaches approaches only clear the cache of the first profile that gets used by Firefox.

Explanation

  1. First, these lines unpack the omni.ja file (a quasi PKZIP file) into the newly created /tmp/omni directory using the unzip utility (extra/unzip 6.0-14).

    cd /tmp
    mkdir omni
    unzip -d omni -q /usr/lib/firefox/browser/omni.ja
    

    -d omni just extracts the files from /usr/lib/firefox/browser/omni.ja into the /tmp/omni directory; -q suppresses output (just a list of files being inflated and extracted).

    unzip will exit with status 2 and you’ll get a warning and an error like this when running the unzip command:

    warning [omni.ja]:  50008544 extra bytes at beginning or within zipfile (attempting to process anyway)
    error [omni.ja]:  reported length of central directory is -50008544 bytes too long (Atari STZip zipfile?  J.H.Holm ZIPSPLIT 1.1 zipfile?).  Compensating...
    

    Don’t worry about it. This doesn’t affect the process; status 2 just means that some error was detected, but “[p]rocessing may have completed successfully anyway”, as the man page says.

  2. Next, these two lines edit the appropriate files in-place. The _preventClickSelectsAll property controls if selection happens on a single click. Setting it to true will prevent this behavior. The first line addresses the URL bar, the second line addresses the search bar.

    sed -i 's/this\._preventClickSelectsAll = this\.focused;/this._preventClickSelectsAll = true;/' omni/modules/UrlbarInput.jsm
    sed -i 's/this\._preventClickSelectsAll = this\._textbox\.focused;/this._preventClickSelectsAll = true;/' omni/chrome/browser/content/browser/search/searchbar.js
    
  3. This creates a new omni.ja with the changed file using the zip utility (extra/zip 3.0-9).

    cd omni
    zip -0DXqr omni.ja *
    cd ..
    

    It’s important to target * (every file) inside omni/, not the omni/ directory itself; we don’t want to create an omni.ja with omni as the root directory. Getting in and out of the directory with cd also ensures the correct file hierarchy, otherwise, zip would still include the additional omni root directory in the archive.

    As for the options, -0 sets the compression level to no compression and simply stores the files; -D avoids creating entries in the zip archive for directories; -X does not save extra file attributes; -q, again, suppresses output; -r ensures that files are added recursively in their correct directory paths.

    These are the options recommended in the MDN documentation. You may have seen an older revision (before I edited it) that uses -9 (-qr9XD, exactly) instead of -0, but this causes issues: for instance, the localization of the tooltips that display keyboard shortcuts fails to load within the developer tools. The answer at Possible to modify hardcoded Firefox JavaScript Ctrl-Tab panel behavior? mentions that -0 is the zip option that creates an omni.ja file with a file size closer to the original file. Incidentally, that’s the only option that avoids this weird localization issue. I explain this in detail in this GitHub issue.

  4. Next, the created omni.ja is moved to the Firefox browser directory (and it replaces the file; don’t directly use an existing omni.ja as the zip target, or else the files will be nested into the existing ZIP), the permissions can be set like the original file, and in the end you can remove the /tmp/omni directory.

    mv omni/omni.ja /usr/lib/firefox/browser/omni.ja
    chown ⟨user⟩:⟨group⟩ /usr/lib/firefox/browser/omni.ja
    rm -r omni
    

    It turns out that the chown command may not be strictly necessary, but it ensures that the new omni.ja has the same owner as the original file. Alternatively, if you copied the original file as a non-root user to a backup directory, you can use this:

    chown --reference=⟨your_backup_directory⟩/omni.ja /usr/lib/firefox/browser/omni.ja
    chmod --reference=⟨your_backup_directory⟩/omni.ja /usr/lib/firefox/browser/omni.ja
    

    Of course, you can use another file, like /usr/lib/firefox/browser/crashreporter-override.ini as a reference.

Restoring an omni.ja backup in case something goes wrong

If Firefox doesn’t seem to be running correctly after this process, or not at all, this process didn’t work, unfortunately. You can restore your backup by a simple mv like this (possibly as root):

mv ⟨your_backup_directory⟩/omni.ja ⟨your_firefox_browser_directory⟩/omni.ja

Remember to purge the caches once again.

If you didn’t create an omni.ja before, you need to re-download Firefox and extract the package to find a replacement omni.ja.


As an aside, the suggested workaround on Bugzilla has a zip --update command. The full commands would be:

unzip -q /usr/lib/firefox/browser/omni.ja modules/UrlbarInput.jsm chrome/browser/content/browser/search/searchbar.js -d omni
# Instead of
#unzip -q /usr/lib/firefox/browser/omni.ja -d omni

… and …

zip -qr9XDu /usr/lib/firefox/browser/omni.ja *
# Instead of
#zip -qr9XD omni.ja *
#mv omni/omni.ja /usr/lib/firefox/browser/omni.ja
#chown ⟨username⟩:users /usr/lib/firefox/browser/omni.ja

Unfortunately, even with the knowledge about zip file hierarchy, I can’t get this to work — it would be nice, though, as it would speed up the process a bit. Instead, I get an error like this when starting Firefox:

XML Parsing Error: undefined entity
Location: chrome://browser/content/browser.xhtml
Line Number 740, Column 15:
              <toolbarbutton id="UITourTooltipClose" class="close-icon"
--------------^

I wonder if Mozilla automatically reports such errors even if I tampered with the build…


Related questions:

  • change selection behaviour of windows address bar
  • How to turn off Firefox address bar auto-selection on focus
  • How to not select the whole text of input when return to focus in Firefox

1: It will likely keep working for later versions, and it probably works for older versions, too; I will only update the versions if this post substantially changes.


I have noticed this behavior as well, but I have a simple workaround. Move your mouse over the address, left click and drag to select some text. Once text has been highlighted you can click anywhere in the string and the cursor will go there.

It becomes second nature and takes no time.