The extension is an example of a
user script manager. It
The extension is an example of a user script
manager. It demonstrates the
userScripts API, the permissions API, optional_permissions, and Manifest
Version 3 (MV3).
and Manifest Version 3 (MV3).
This example demonstrates these aspects of extension development:
-
Showing an onboarding UI after installation.
-
Designing background scripts that can restart repeatedly with minimal overhead. This is especially relevant to Manifest Version 3.
-
Minimizing the overhead of background script startup. This is relevant because Manifest Version 3 extensions use an event-based background context.
-
Monitoring grants for an optional-only permission (
"userScripts"), and dynamically registering events and scripts based on its availability. -
Using the
userScriptsAPI to register, update, and unregister user script code. -
Isolating user scripts in individual execution contexts (
USER_SCRIPTworld), and conditionally exposing custom functions to user scripts.
After loading, the extension detects the new installation and opens the options
page embedded in about:addons. On the options page:
- Click "Grant access to userScripts API" to trigger a permission prompt for the "userScripts" permission.
- Click "Add new user script" to open a form where a new script can be registered.
- Input a user script, by clicking one of the "Example" buttons and input a example from the userscript_examples directory.
- Click "Save" to trigger validation and save the script.
If the "userScripts" permission is granted, this schedules the execution of the registered user scripts for the websites specified in each user script.
See userscript_examples for examples of user scripts and what they do.
If you repeat steps 2-4 for both examples and then visit https://example.com/, you should see this behavior:
- Show a dialog containing "This is a demo of a user script".
- Insert a button with the label "Show user script info", which opens a new tab displaying the extension information.
Showing onboarding UI after installation:
background.jsregisters theruntime.onInstalledlistener that callsruntime.openOptionsPageafter installation.
Designing background scripts that can restart repeatedly with minimal overhead:
- This is particularly relevant to Manifest Version 3, because in MV3 background scripts are always non-persistent and can suspend on inactivity.
- Using
storage.sessionto store initialization status, to run expensive initialization only once per browser session. - Registering events at the top level to handle events that are triggered while the background script is asleep.
- Using dynamic import to initialize optional JavaScript modules on demand.
Monitoring an optional permission (userScripts), and dynamically registering
events and scripts based on its availability:
events and scripts based on its availability:
-
The
userScriptspermission is optional and can be granted by the user from:- the options page (
options.html+options.mjs). - the browser UI (where the user can also revoke the permission). See the Mozilla support article Manage optional permissions for Firefox extensions.
- the options page (
-
The
permissions.onAddedandpermissions.onRemovedevents are used to monitor permission changes and, therefore, the availability of theuserScriptsAPI. -
When the
userScriptsAPI is available whenbackground.jsstarts orpermissions.onAddeddetects that permission has been granted, initialization starts (using theensureUserScriptsRegisteredfunction inbackground.js). -
When the
userScriptsAPI is unavailable whenbackground.jsstarts, the extension cannot use theuserScriptsAPI untilpermissions.onAddedis triggered. The options page stores user scripts instorage.localto enable the user to edit scripts even without theuserScriptspermission.
Using the userScripts API to register, update, and unregister code:
- The
applyUserScripts()function inbackground.jsdemonstrates how to use the varioususerScriptsAPIs to register, update, and unregister scripts. userscript_manager_logic.mjscontains logic specific to user script managers. Seeuserscript_manager_logic.mjsfor comments and the conversion logic from a user script string to the format expected by theuserScriptsAPI (RegisteredUserScript).
Isolating user scripts in individual execution contexts (USER_SCRIPT world),
and conditionally exposing custom functions to user scripts:
-
Shows the use of
USER_SCRIPTworlds (with distinctworldId) to define sandboxes for scripts to run in (seeregisteredUserScriptinuserscript_manager_logic.mjs). -
Shows the use of
userScripts.configureWorld()with themessagingflag to enable theruntime.sendMessage()method inUSER_SCRIPTworlds. -
Shows the use of
runtime.onUserScriptMessageandsender.userScriptWorldIdto detect messages and the script that sent messages. -
Shows how an initial script can use
runtime.sendMessageto expose custom APIs to user scripts (seeuserscript_api.js).
The userScripts API is available from Firefox 136. In Firefox 134 and 135, the
functionality is only available if the extensions.userScripts.mv3.enabled
preference is set to true at about:config before installing the extension.