WebExtensions/TabHiding
This document is an attempt to distill down the comments in 1384515 and 1332447. The intent of this document is to clarify the API and assist in getting this landed into Firefox.
The experiment done by Dietrich is on github. Here is a movie of it working on Nightly. Big shout out to Dietrich for getting it so far! 👏🍹
Overall
Some of the key goals of WebExtensions are that it’s not about changing the Firefox UI in the way we used to in legacy add-ons. There’s clear limitations we need to set. However there’s so much interest around tabs and tab groups.
- Some of the key principles around WebExtensions are:
- Extensions changing large parts of the interface should be done when it’s clear it’s caused by an extension. Examples are: on install, blocking on user input.
- Extensions should clean up after themselves when uninstalled.
- Users should have notification of what an extension does, especially to the Firefox UI.
- It shouldn’t be dependent upon add-on reviewers to enforce security UI requirements.
Timeline
This is an ongoing project to provide an API that an extension can use. The end goal should be a sophisticated set of APIs that would allow a lot of tab choices for users and developers. However it might take some time to get there.
Whilst this is being built out, developers should understand that this is an experimental API and subject to change.
Milestone 1: Basic APIs
Land an API developers can use to hide tabs, 1384515. Until we’ve got the security and notification issues fixed, this should cause tabs to be suspended by default.
We’d also need to add in:
- onUpdated events
- The appropriate property to the tabs.Tab object
This will require the permission to be added to inform the user whats going.
Hiding the tab strip, 1332447 completely could land, but won’t be a priority. It should be behind a preference that the user must explicitly set until the security issues (milestone 2) are resolved. It should be a manifest key set at install time.
Milestone 2: Notification
Work on the security and notification issues, which are mostly detailed in 1408053. We’ll need to engage with UX in order to work on that.
With the landing of notification and the tabs.discard API we will remove the requirement to suspend a tab and let the add-on author choose if they want to suspend or not.
If the tab strip has landed, allow that to run without a pref.
Milestone 3: Improvements
Possibly allow the tab strip to be hidden dynamically from user interaction.
Adding of any additional events.
API
Note: The tabshideshow namespace is a consequence of being an experiment. This would probably be part of the tabs namespace.
Manifest
Status: not implemented in experiment
“theme”: { “tab_bar_visible”: false }
On install, this would hide the tab bar. On uninstall this would restore the tab bar.
Later improvements would possibly dynamic handling of the tab bar. The experiment had:
browser.tabshideshow.setTabBarVisible
Functions
Status: implemented in experiment
tabshideshow.show([tabIds...]) tabshideshow.hide([tabIds…])
These would hide or show individual tabs. The default tab strip implementation of Firefox would work with those values. Other tab strip implementations would deal with these if they chose to.
Notes:
- Pinned tabs are unaffected by this API.
- You cannot hide the currently active tab in a window.
- If the last visible tab in the window is closed, we'll close the whole window, including the hidden tabs.
- On uninstall, hidden tabs should become unhidden again.
These essentially call showOnlyTheseTabs method in tabbrowser.xml: https://dxr.mozilla.org/mozilla-central/source/browser/base/content/tabbrowser.xml#3796
Events
Status: not implemented in experiment
tabs.onUpdated
We’ll need to ensure that onUpdated gets fired when it changes state with the appropriate value in Tab.visible. That should enough for extensions to monitor when the tab gets removed.
Querying
Status: not implemented in experiment
Tab.visible
We’ll need to able pass the visible value to the query API. Let’s make it so the default is to only query visible tabs. If the tab strip is hidden, then what should this value be? Should we assume that it’s up to the add-on implementing the tab strip to set the hide and show values correctly?
Permissions
Status: not implemented in experiment
tabManagement
User prompt (proposed): Manage your tabs Optional: No. Since the manifest permission is not accessible at runtime. As a later optimisation we could go for more fidelity there if we felt it warranted it.
Security concerns
The following security concerns have been added to this tracking bug: 1408053
WebExtensions is a sandbox and the goal is to make WebExtensions more secure than the legacy add-ons. We need to learn from the mistakes that were made in the past and not repeat them. That means any API we release must be secure and we feel comfortable about it.
Security concerns with hiding tabs:
- A tab running without the user’s knowledge presents many risks
- Could be doing a highly intensive task in the background that the user doesn’t know about because the tab is hidden.
- Could track the user across different networks (privacy risk)
- Could spawn windows, ads, annoying or belligerent content
- Could make network requests that are inappropriate for network (personal websites at work etc)
- A tab could be using something annoying or invasive
- Audio
- WebRTC
- Anything else
- Also “we may also glow when a tab does a window.alert() in the background and that site was disallowed from stealing focus”
- How would Basic Authenticaion (tab modular, grabs focus) be handled?
- Legacy security prompts, SSL cert install, CRMFRequest etc
- Long running js warning?
If an add-on is hiding tabs then it should be able to provide information on what the tab is doing, in good faith. For example: you can display audio information (tabs.Tab.audible) but you can’t tell if the tab is doing WebRTC. We also have to think about all the various security prompts/events ( mozbrowserusernameandpasswordrequired etc etc etc etc)
However it’s time consuming and dangerous to try and manually audit each add-on to see if it replaces the built in security mechanisms with its own. Our only real solution is to ensure that if a tab is hidden (or all tabs are hidden) that we:
- Show to the user that tabs are hidden and provide to
- List the tabs that are hidden
- See the information that the tabs would normally give you (url and title)
- Provide a way out of this
- Show indicators, when a tab is using anything annoying or invasive (eg: Audio or WebRTC)
- Handle all the tab modal security events appropriately (http auth, cert instal etc etc)
- Provide a way for the user to see which add-ons are configured to manage tabs?
- Ability to enable/disable tab managers
Random Notes
Most of these aren’t a concern.
- If a developer passes through a tab that can’t be hidden, it should throw a message and continue with the rest of the tabs.
- The tabs API is async and so the question of what happens if an extension fires too many requests is similar to any API in tabs ([27]).
Kevin has implemented tab.discard in 1322485 which will allow suspending tabs independent of hiding. That will allow tabs to be suspended and I believe, with the UI notification, we’ll be able to separate suspending out of this argument, which mostly came up in [24].
Chrome doesn't do this and I’ve not see any indication it plans on doing it.
Allows you to shelve tabs off to the side. Let’s reach out to Microsoft see if they plan on making an API for this. Shelving a tab appears to suspend it. Audio/video stops and unshelving it starts a YouTube video from the beginning again. These tabs persist outside of the window. They can be unshelved into a different window and after closing and reopening Edge they are still shelved. Here's a [of it].