Jeff Johnson (My apps, PayPal.Me, Mastodon)

Feedback Assistant Boycott

Safari bookmarklet permissions

June 22 2024

A bookmarklet is a bookmark stored in a web browser that contains JavaScript commands. Here's a simple, useless example:

javascript:alert('Hello,%20World!');

To run bookmarklets in Safari on macOS, you need to enable "Show features for web developers" in Safari Advanced Settings and "Allow JavaScript from Smart Search field" in Safari Developer Settings.

Michael Tsai of C-Command Software has a list of some useful bookmarklets for his app EagleFiler. Here's an example that archives the URL and title of a web page in EagleFiler, using its x-eaglefiler custom URL scheme:

javascript:window.location='x-eaglefiler://import?url='+encodeURIComponent(window.location)+'&format=webloc&title='+encodeURIComponent(document.title);

The problem is that Windows Vista, err, Safari requests permission to open a URL in another app.

Do you want to allow this website to open EagleFiler.app?

As I explained in a blog post last year, when you select Always Allow, the permission you granted is stored in a database.

sqlite3 ~/Library/Safari/PerSitePreferences.db .dump | grep PerSitePreferencesOpenApplications
INSERT INTO preference_values VALUES(9,'underpassapp.com','PerSitePreferencesOpenApplications','x-eaglefiler',NULL,NULL,NULL);

The permission is per-website, which means that every time you use the EagleFiler bookmarklet on a different website, Safari requests your permission again!

When Michael presented me with this problem, I said to him, "I have spent my whole life trying to figure out crazy ways of doing things. I'm telling ya, as one engineer to another - I can do this." Ok, that was actually Scotty to Geordi in the episode "Relics" from Star Trek: The Next Generation, but I find the quote inspiring, and I have indeed spent my whole career trying to figure out crazy ways of doing things. To wit:

javascript:var%20w=window.open();var%20a=w.document.createElement('a');a.href='x-eaglefiler://import?url='+encodeURIComponent(window.location)+'&format=webloc&title='+encodeURIComponent(document.title);w.document.body.append(a);a.click();

This JavaScript first calls window.open(), which creates a new about:blank tab. It then creates an HTML anchor element—in other words, a hyperlink—adds the link to the about:blank document, and clicks the link automatically. The link opens the desired x-eaglefiler URL. When you select Always Allow at the permissions prompt, the database adds a new entry:

INSERT INTO preference_values VALUES(10,'','PerSitePreferencesOpenApplications','x-eaglefiler',NULL,NULL,NULL);

This time the value of the domain is empty (''), because about:blank has no domain. The about:blank trick allows you to use the same bookmarklet on every website without any additional permission prompts!

After you've granted permission to the empty domain, you can append w.close(); to the bookmarklet so that the new tab closes automatically.

Obviously, the same technique will work for other bookmarklets that have different URL schemes and URL formats. It's generalizable. Instead of trying to set window.location in your bookmarklet, which uses the permissions of the current page, fake click a fake link in a new empty tab, which uses the permissions of empty tabs.

Feedback Assistant Boycott

Jeff Johnson (My apps, PayPal.Me, Mastodon)