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! šš¹
Contents
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
Bugs
Main tracking bug: 1410548
5 Total; 5 Open (100%); 0 Resolved (0%); 0 Verified (0%);
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 (comment 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 comment 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 video of it.