New in WebExtensions: action.openPopup
I've been attending the Web Extensions Community Group since it started early last year. While the group is still in an early stage, it has already led to some exciting changes shipping in browsers. Today I want to talk about the action.openPopup
API, one example that I'm particularly excited about.
What's action.openPopup?
One unique feature of WebExtensions is the ability to render in to a "popup", a popover which is usually attached to the extension's toolbar icon and gives the extension some space to draw UI above any webpage the user is looking at. This can be a useful place for a user to interact with an extension, especially since it crosses the 'line of death' and is therefore more trusted than any interactions the user has with an extension from within the page.
action.openPopup
gives us a way to programatically display the popup - rather than the user having to explicitly invoke it from the toolbar. This can be useful to make it invokable in other ways - for example, the old Google Cast extension used to use an internal version of this API to show the cast UI.
The API
Usage looks a little bit like this:
// Open the popup for the current window. await browser.action.openPopup(); // Open the popup for the window with ID 1. await browser.action.openPopup({ windowId: 1 });
For the most up to date look at the API, Google's API proposal is a great place to start. MDN also has documentation - I've opened some PRs to update it (here and here) to reflect the latest changes.
The journey so far
Here's the exciting bit - just over a year ago, Firefox was the only browser with support for this API, and it had to be triggered in response to a user gesture. Since then:
- Google has begun to prototype an implementation of this API (crbug.com/1245093). It's available in Chrome Canary for extensions using Manifest V3.
- Safari shipped support in Safari 16, for both desktop and iOS. They even linked the WECG issue in the WebKit release notes!
- Firefox is being updated to remove the user gesture requirement and support the new
windowId
parameter (tracking issue).
A closer look at Firefox
I wanted to talk a bit more about Firefox because I've been particularly involved there. As mentioned, Firefox have supported this API for a while, but it was only available when a user gesture was present. Additionally, since it was added before Chrome's API design, it was missing support for the windowId
parameter. In a bug, Mozilla confirmed they were open to patches. Working with Rob Wu at Mozilla I was able to land D139796 which makes some changes here, currently limited to Nightly. We're now working to finalise some of the more nuanced behaviours so we can hopefully bring the changes to stable soon. Do feel free to give it a try and share any feedback before then!
What's left
There are many inconsistencies between browsers which need to be resolved. These are being discussed in #160 and we agreed in the last Community Group meeting (minutes) to start describing the behaviour more formally in the specification.
Here's a taste of some of the behaviour across browsers today, taken from the testing I've been doing in that issue:
Behaviour | Chrome | Safari 16+ |
---|---|---|
Calls onClicked handler with popup | No | No |
Calls onClicked handler without popup | No | No, focuses window |
Default window | Active tab in topmost window | Active tab in topmost window |
Can call for private window | Unable to test (see here) | Yes |
Closes popup when open | Throws error (no active browser window) | No, focuses window |
Closes popups from other extensions | Throws error (no active browser window) | Yes |
Requires user gesture | No | No |
Grants activeTab permission | No | Skips permission prompt, API calls hang. Reloading the popup window restores ability to make API calls and request permissions. |
User gesture grants activeTab | No | NA - content script injection is tied to granting host permissions |
Callable from content script | No | No |
Behaviour after .disable() call | Throws error (no popup for tab) | Ignored, popup continues to open |
Behaviour when hidden in browser-specific UI | Icon is revealed, popup opens | Window focused, popup does not open |
windowId for minimized window | Unable to test (see here) | Window is maximised |
windowId for hidden window | Unable to test (see here) | Popup opens, window only focused if Safari is active app |
In conclusion
We're not quite there yet! But this API is getting closer fast, and with feature detection it's possible to start using this API today. If you're interested in this capability, do join in with the discussions in the WECG repo. The more feedback the better! I'm also happy to chat to anyone with an interest in this.