Oliver Dunk

Oliver Dunk

22 years old, Developer at 1Password

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?

Hello World extension showing popup

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.


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:

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.