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

Feedback Assistant Boycott

How Safari can improve extensions

January 9 2024

As a longtime Safari extension developer, I have a number of suggestions about how Safari could improve its extension support. I've already filed some of these suggestions with Apple's Feedback Assistant, but since I'm now boycotting Feedback Assistant, I thought I'd post the list on my blog. Another benefit of blogging the suggestions is of course that other people can read them, unlike in Feedback Assistant, which is a closed, opaque system. I'll start with user interface improvements and then move on to technical matters relevant for extension developers.

1. Bring the Manage Extensions widget to Mac from iPad

In Mac Safari, extensions can be accessed only if their buttons are in the toolbar.

Mac Safari window toolbar

This can be a problem if you have a lot of Safari extensions. Even if some of them are accessed infrequently, they all need to take up space in the toolbar, because otherwise you can't access them at all.

In iPad Safari, on the other hand, there's a Manage Extensions widget in the toolbar that opens a popup giving access to every extension.

iPad Safari Manage Extensions toolbar widget

Chrome and Firefox both have a similar toolbar widget to manage extensions.

Google Chrome window toolbar   Firefox window toolbar

Thus, it seems obvious that Mac Safari ought to have a Manage Extensions toolbar widget too.

2. Bring toolbar customization to iOS from Mac

iOS has the opposite problem: you can manually customize the Safari toolbar in Mac Safari but not in iPad Safari. Extensions that are enabled on the page appear in the toolbar, whether you want them or not, and extensions not enabled on the page don't appear in the toolbar, whether you want them or not.

iPad Safari window toolbar

In iPhone Safari it's is even worse, because extensions can get lost deep in the toolbar popup menu.

iPhone Safari toolbar popup iPhone Safari toolbar popup scrolled

There ought to be a way to customize which extensions appear in the toolbar on iPad and in the toolbar popup menu on iPhone.

Chrome can pin an extension button to the toolbar from the manage extensions popup menu, and Firefox can pin an extension button to the toolbar from the contextual menu.

Chrome pin button Firefox Pin to Toolbar

3. Add extensions permissions to the Website Settings popup

Safari extensions require permission to access websites, but there's not an easy way to access those permissions. In Mac Safari, the permissions are in the separate Settings window.

Mac Safari Websites Settings

In Mobile Safari it's even less convenient, because the permissions are in the separate Settings app, buried deep in submenus.

Safari Extensions Settings

It would be nice if the extensions permissions were in the Safari Website Settings popup.

Mac Safari Website Settings popup
iPhone Safari Website Settings popup

This is especially important for revoking extension permissions. An extension that has "Ask" permission can be granted "Allow" permission to a website by clicking on the extension's button in Safari.

The extension StopTheScript would like to access en.wikipedia.org

However, once permission is granted, there's not a convenient way to revoke that permission.

4. Don't distinguish between content blockers and extensions

Previously I've blogged about the four types of Safari extension: Safariextz (defunct), Safari content blocker, Safari app extension, Safari web extension. Users do not understand the difference between these types. My own StopTheMadness is a Safari app extension on Mac and a Safari web extension on iOS. Yet people think that StopTheMadness is a content blocker, and they email me complaining that they've turned off content blockers on a website, but StopTheMadness is still active on the site, as if that were a bug in my extension.

Turn Off Content Blockers

Safari should not distinguish between content blockers and extensions, because users have no idea what that distinction means.

Curiously, Safari does combine content blockers and extensions in some places, eliding the distinction. Below, my StopTheFonts is a Safari content blocker, while the others are extensions.

iPhone Safari Extensions Settings

Mac Safari Extensions Settings

Nonetheless, the confusing distinction exists elsewhere.

Mac Safari Websites Settings

5. Document the extension highlight color

Have you ever wondered why some Safari extension icons are blue?

Safari extension icon blue tint

On the Mac, the tint actually depends on your "Accent color" in Appearance System Settings. There's no such setting on iOS, which is why it's always blue in Mobile Safari.

The purpose of the tinting is to indicate that the extension has permission to access the web page currently displayed in Safari. Did you know that? Many people don't. A couple of years ago I wrote about mass confusion and dislike over Safari extension icon tinting:

It's important to note that is there's no official Apple documentation explaining the significance of Safari extension toolbar icon tinting. I've looked everywhere in Safari and also searched extensively in Apple's support pages. The only way that anyone knows how this works is that occasionally a Safari engineer will respond to someone's perplexity. But this haphazard approach obviously doesn't scale to over a billion Safari users.

As far as I can tell, the situation hasn't changed since then. There's still no documentation of this "feature", which is ridiculous, especially when the entire purpose of it is supposedly to communicate information to users.

6. Bring missing extension API to iOS from Mac

On macOS there's an API (Application Programming Interface) SFSafariExtensionManager getStateOfSafariExtension that allows an app to determine whether its Safari extension is enabled, and there's an API SFSafariApplication showPreferencesForExtension that allows an app to open Safari Extensions Settings to show the extension. These API are used to help guide the user to enable an app's Safari extension, but the API don't exist on iOS, which makes it more difficult and confusing for users to enable Safari extensions on iOS.

Apple's developer document Assessing your Safari web extension’s browser compatibility lists a number of Safari extension API that are available on Mac but not on iOS. From my perspective, one of the most crucial missing API is windows create, which allows an extension to create a new window in Safari. (iOS extensions can create new tabs but not new windows.) Without this API, there's no way for a Safari extension on iOS to open a URL in a private window. Or in a non-private window, for that matter. Ironically, an iOS Safari extension can detect whether a tab is in a private window or not, but the extension has no control over whether to open tabs in private or non-private windows. I would love to have this feature in StopTheMadness.

7. Combine the app extension and web extension API

As I explained in my blog post the four types of Safari extension, Safari app extensions are a Mac-exclusive, Safari-exclusive type of extension introduced in 2016, whereas Safari web extensions are a cross-platform and cross-browser type of extension introduced on Mac in 2020 and iOS in 2021. In Safari version 17, Safari app extensions finally got the website-specific permissions system that Safari web extensions had from the beginning. Yet significant differences remain between the two types of extension. This makes life particularly difficult for me, because StopTheMadness on Mac, introduced in 2017, is a Safari app extension, but StopTheMadness on iOS is a Safari web extension. Each type of extension has its own advantages and disadvantages, its own capabilities and limitations. It would be wonderful if the two API were combined, so that extension developers could take advantage of both and experience the best of both worlds.

Oddly, like Safari web extensions on iOS, Safari app extensions lack the ability to open new private windows, though they can open new non-private windows, unlike Safari web extensions on iOS. The app extension API is SFSafariApplication openWindowWithURL, which has no option for private browsing. Again, though, Safari app extensions can detect private windows with the SFSafariPageProperties usesPrivateBrowsing API, so the limitation doesn't make much sense. My workaround for this limitation was to create a separate, dedicated app to open URLs in Safari private windows. Unfortunately, though, this is possible only on Mac, not on iOS, because my app actually uses AppleScript to click items in Safari's main menu.

One massive advantage of the Safari app extension API is that it allows the extension to display a native AppKit user interface in the Safari extension popup, while Safari web extensions must rely exclusively on HTML and CSS. I would love to be able to display a native UIKit user interface in Safari extension popups on iOS, because HTML is so clunky, limited, and ugly in comparison.

8. Fix the extension bugs

I've posted a list of my Safari extension bugs on GitHub. This list is for the benefit of all Safari extension developers, and other developers are also welcome to post their Safari extension bugs in the list. As I mentioned before, Apple's Feedback Assistant is a closed system, so unfortunately there's no way to view or search for bug reports other than your own. Naturally, there's some overlap between the list of bugs I've filed with Apple and the issues I've discussed in this blog post. Two egregious issues that I haven't mentioned here are a website permissions data loss bug on iOS and a content script loading bug on macOS, the latter of which has plagued me for more than three years.

Oh, and the other day I somehow made Mobile Safari crash on iOS 17.2.1.

Thread 3 name:   Dispatch queue: com.apple.extension.global-state-queue
Thread 3 Crashed:
0   libsystem_blocks.dylib        	       0x211c8aa00 _Block_copy + 56
1   libsystem_blocks.dylib        	       0x211c8a9b8 -[__NSMallocBlock__ retain] + 23
2   ExtensionFoundation           	       0x1b6ccc4bc __93-[EXConcreteExtension _completeRequestReturningItems:forExtensionContextWithUUID:completion:]_block_invoke + 59
3   libdispatch.dylib             	       0x1afc976a8 _dispatch_call_block_and_release + 31
4   libdispatch.dylib             	       0x1afc99300 _dispatch_client_callout + 19
5   libdispatch.dylib             	       0x1afca0894 _dispatch_lane_serial_drain + 747
6   libdispatch.dylib             	       0x1afca13c4 _dispatch_lane_invoke + 379
7   libdispatch.dylib             	       0x1afcac004 _dispatch_root_queue_drain_deferred_wlh + 287
8   libdispatch.dylib             	       0x1afcab878 _dispatch_workloop_worker_thread + 403
9   libsystem_pthread.dylib       	       0x211c8f964 _pthread_wqthread + 287
10  libsystem_pthread.dylib       	       0x211c8fa04 start_wqthread + 7

9. Fix the web inspector bugs

I like the user interface of the Safari web inspector. Indeed, I prefer it to other web browsers. However, the bugs in the Safari web inspector drive me nuts and sometimes make my job almost impossible. I'm talking about serious bugs such as slowdowns, hangs, and crashes. I don't see this happen in other web browsers. I currently have 14 open web inspector bugs—not including feature requests—in the WebKit Bugzilla, and I generally file reports only for reproducible bugs; the randomly encountered bugs are also numerous, but I know they're unlikely to be addressed from my reports. It seems to me that there might be something fundamentally wrong with the Safari web inspector architecture if the user interface frequently becomes unresponsive. Lately a hang in the web inspector has been making it very difficult for me to work on video-related features for StopTheMadness. The worst bug, though, is data loss caused by opening the Safari web inspector. I'm losing all of the LocalStorage and IndexedDB for every website I visit! The result is that I get logged out of some sites, and lose saved settings on other sites. Quite annoying and inconvenient.

Conclusion

There's a lot more that I could say about Safari extensions, but then this blog post would go on forever, to the benefit of no one. Moreover, I tried to stick to "engineering" issues here, avoiding "policy" issues that are somewhat controversial and might require decisions upward in the Apple management chain. I think that everything I mentioned in my list is fairly straightforward and uncontroversial. The only real controversy is whether Apple is willing to devote the time and resources to address these suggestions that would improve extension support in Safari. I hope so!

Addendum January 10 2024

I wrote about Safari extension updates just 6 weeks ago, but I should have mentioned that subject here too. Safari needs to handle them better.

Feedback Assistant Boycott

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