Porting your Chrome extension to Safari

April 29 2021 by Jeff Johnson

Safari version 14 for macOS, released last year, added support for the cross-platform Web Extensions API. The intention was to make it much easier to port your Chrome extensions to Safari, by allowing you to use the same code on each platform. (This applies to Firefox extensions too, but I'm going to focus on Chrome, because that's where the main interest seems to be for Safari ports.) In the ideal case, your Chrome extension's code will "just work" in Safari, no changes required. Believe it or not, even chrome.* JavaScript API calls work in Safari! But there's a catch. You knew there'd be a catch. Or several catches. In this blog post, I'll give an overview of the issues you may face in porting your Chrome extension to Safari.

1. Mac App Store

All Safari web extensions — that is, Safari extensions using the cross-platform Web Extensions API — must be distributed via the Mac App Store. Unfortunately, there's no alternative distribution method. This is a change in policy, since it is possible to distribute Safari app extensions — Safari extensions using the earlier Apple-specific Safari extensions API — outside the Mac App Store, via Developer ID. For example, my own Safari app extension StopTheSwift can be downloaded directly from my web site. (There are now two different kinds of Safari extension, in case you weren't confused enough yet.) I don't know why Apple changed policy for Safari web extensions, but there's effectively no way around the policy. Safari will simply refuse to load Developer ID signed web extensions. (In Safari's "Develop" menu, you can select "Allow Unsigned Extensions", which will then request your keychain password, and then allow any extension to load. But this resets every time you relaunch Safari, and its purpose is for developing and testing Safari web extensions, not for distributing them.) I suppose that Apple would claim App Store review of extensions is needed for "security", but we know from recent court testimony that App Store review is quite superficial and typically lasts only a few minutes. ¯\_(ツ)_/¯

2. Apple Developer Program

Submitting to the Mac App Store requires membership in the Apple Developer Program. The membership fee is $99 USD plus tax per year. There are fee waivers available for "eligible organizations", i.e., nonprofit, education, and government entities, but there's significant red tape involved, and the waivers are not available to individuals, even if your extension happens to be open source. (Apple never gave fee waivers to open source iOS or Mac apps either.) Thus, most people will have to pay. And you must maintain your membership, otherwise your extension will be removed from the Mac App Store. If you're not already a member of the Apple Developer Program, then porting your Chrome extension to Safari will cost you at least $99 per year, indefinitely. (This is in contrast to the one-time $5 fee to submit extensions to the Chrome Web Store.) The "good news" is that even if you later decide to discontinue membership in the Apple Developer Program, and Apple removes your extension from the Mac App Store, the extension will continue to work for your users who already downloaded it. Apple does not "pull a remote kill switch" in that case, thankfully.

In joining the Apple Developer Program, you'll have to agree to its terms and conditions. You may or may not be ok with that. I won't discuss them here and have no legal advice other than to read before you sign. (I didn't follow my own advice, because I'm a hypocrite.)

3. Mac App Wrapper

Extension developers are accustomed to writing JavaScript, HTML, and CSS. Perhaps the biggest surprise in porting your Chrome extension to Safari is that Safari web extensions require a native Mac app wrapper. The rationale behind this requirement is even more baffling than the App Store requirement, because very few Chrome extension developers have Mac app development experience. To create a Safari extension, you first need to install Xcode and become familiar with how Xcode works. This may be a daunting experience for someone who has never done Apple development. Xcode itself is a massive (like 30 GB massive), complex beast that is used for all Apple platform development: iPhone, iPad, Mac, Apple TV, Watch, and Safari. Fortunately, Xcode comes with a built-in conversion tool to automatically create a Mac app wrapper for your existing Chrome extension. If you're not too picky, that could be "good enough", and you probably won't have to write any native Swift or Objective-C code. The default Mac app wrapper for web extensions is a very simple GUI that instructs the user to enable the extension in Safari's Preferences. Otherwise, the app has no real purpose. It's just a container for the extension, an appendage of the Mac App Store requirement. In any case, though, you'll need to learn how to build your app in Xcode, and how to upload it to App Store Connect.

For an experienced Mac app developer (such as myself), creating a Mac app wrapper for a Safari web extension is a relatively trivial task, requiring very little time and effort. If you have no Apple development experience yourself, you might consider finding a Mac developer to help you through the process. You could do it yourself, but be prepared for a steep learning curve.

4. Web Extensions API

Safari support for the Web Extensions API was just added less than a year ago. At present, the implementation is very far from complete. A number of features are missing. This appears to be partly intentional — for "security" or "privacy" or whatever reason, the Safari team has no intention of implementing certain Web Extension features — and partly unintentional, a consequence of Apple shipping Safari web extension support before it was "fully baked". There are also a lot of bugs, which I assume are unintentional. For example, there's a bug with document_start that's particularly painful to me, because the bug renders practically useless the Safari web extension I've been wanting to release ever since Safari web extensions were first announced. Sigh. Anyway, you may have no problems with the API, or you may have a showstopping problem, but you probably won't know whether the existing Safari web extensions implementation is adequate for your purposes until you convert and test your Chrome extension in Safari. However, there is some useful compatibility documentation that you can review beforehand.

The elephant in the room is uBlock Origin. This is the extension that everyone asks about, that everyone wants ported to Safari. And I'm sorry to say, but it's not going to happen. It can't happen. Apple's compatibility documentation specifically says of the webRequest API, "Blocking requests not supported." In other words, uBlock Origin not supported. And the Safari team has been very clear that their preferred option is their own Apple-specific Safari content blocker API. (Which extension developers know is inferior, but that debate is… fruitless.)

5. Safari Intelligent Tracking Protection

Assuming the Safari Web Extensions API works as you expect for your Chrome extension, there's still another possible barrier to porting: every web browser has its own "quirks", and Safari is no exception. (Or should I say, Safari is an exception?) One feature of Safari that often trips up Chrome developers is Intelligent Tracking Protection ("Prevent cross-site tracking" in Safari's Privacy Preferences). ITP is enabled by default in Safari, which can make Safari behave differently than Chrome. There is an option "Block third-party cookies" in Chrome's settings that's somewhat similar, but it's currently off by default. Especially in cases where your Chrome extension works alongside your web site, you may find that some feature you've always counted on to work in Chrome suddenly doesn't work in Safari.

Although you may experience issues, I wouldn't recommend that you use Safari ITP as an excuse to avoid porting your Chrome extension to Safari. After all, you may soon be experiencing the same kind of issues in Chrome too. Google has already announced that they intend to eliminate third-party cookies. And some people (including myself!) already disable third-party cookies in Chrome. In some sense, the experience of porting your Chrome extension to Safari may be a useful wake-up call. All of the web browsers are innovating rapidly in the area of privacy, so as an extension developer you don't want to be caught unaware of those changes and be left in the dust.

6. Help?

Honestly, don't expect much help. There's a section in the Apple Developer Forums where Apple engineers sometimes respond to questions, but the response is typically "Please file a bug", which is not very helpful. There doesn't seem to be a large community of developers porting extensions to Safari, so if you have a question or a problem, there may not be anyone available to help you. I've seen a number of unanswered questions on Stack Overflow too. On the other hand, your Apple Developer Program membership does include two Technical Support Incidents per year, and you can purchase more. These give you direct access to Apple support engineers, so perhaps they could help you if you have problems.

7. Conclusion

Since the release of Safari 14, a number of Chrome extensions have already been successfully ported to Safari, and more are to come. In this blog post, I've tried to give an overview of what issues you may face when porting your Chrome extension to Safari, so you can go into the process with realistic expectations. Porting to Safari may not be for everyone, but I certainly don't intend to dissuade you, otherwise I wouldn't have bothered to explain how it all works. It can work, and hopefully this post is useful to extension developers who have been thinking about porting to Safari.

Jeff Johnson (My apps, PayPal.Me)