In case you don’t know, when you click a link by default most browsers will send the URL of the site on which the link was to the site you’re going to as the “Referer” (the spelling is a typo that made it into the specification). There are some uses for this, for example if you get to this blog via a link I can see that in the statistics, but it can also be a privacy issue. That’s why I wrote an add-on that can change, or simply remove that information.
document.referrer property (oh hey, spelled correctly there!). It’s basically the same thing, except instead of being sent to the server it’s available to scripts running on the site, with the same possible privacy issues. At the time I didn’t have time to look into it, but later someone else was so kind to look into it and leave a comment: Firefox used to make
document.referrer match the HTTP
Referer, but there’s a bug since version 69 that stopped that. The comment also included a link to how another add-on called “Smart Referer” solved the problem.
So yesterday I set out to find my own solution. From looking at the Smart Referer code I knew I’d need to add a content script to Referer Modifier, code that would run in the context of each loaded site. But I didn’t like their approach of getting configuration to the content script, which runs in a limited environment: They generated the script (as text) at runtime, and included the configuration in that text as JSON. I guess it works, but it seems overly complicated.
Looking around MDN (highly recommended for any kind of web stuff!) I found that there’s a messaging mechanism specifically for communication between different parts of an add-on:
runtime.sendMessage(). It’s perfect for my purposes: The content script can send a message to the background script of the extension containing the URL of the current page and the pre-set
document.referrer, and the response will tell it how to overwrite the latter. That way there’s no need to generate code, and I could just write it as a (pretty short) script file that Firefox will load when a page is loaded. Also the code that checks the configuration is literally the same, no unnecessary complexity there!
In the existing background script I just had to add a listener for incoming messages, and write a function to send the responses. It took a little while though to figure out why I’d get “invalid URL” errors when trying to parse the default
document.referrer and it was unset. Turns out while I was checking for
null, “unset” is actually an empty string in this case.
That was a fun little exercise, and here’s the patch with everything put together if you’re interested. 😉