Fun with Javascript, or: Setting document.referrer

It’s a bit of an odd thing for me to say, but yesterday I had some fun playing with Javascript. I maintain a little Firefox add-on called “Referer Modifier” to modify the HTTP Referer header, an since Web Extensions became the standard for browser extension Javascript is simply the language of choice for that.

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.

A while ago someone asked if the add-on would also support changing the Javascript 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. 😉

Leave a Comment

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: