Customizing Firefox Context Menus with browser.menus API
This article explains how the browser.menus API enables
developers to add custom actions to the Firefox right-click context
menu. By declaring the correct permissions in the extension's manifest
file, defining menu items in a background script, and registering event
listeners, extensions can provide users with context-specific tools for
interacting with web pages, selected text, media, and the browser
interface itself.
1. Requesting Manifest Permissions
To use the browser.menus API, an extension must first
request the menus permission in its
manifest.json file. Without this declaration, the browser
will block access to the API.
{
"manifest_version": 3,
"name": "Custom Context Menu Extension",
"version": "1.0",
"permissions": [
"menus"
],
"background": {
"scripts": ["background.js"]
}
}Note that Firefox also supports the contextMenus
permission as an alias for compatibility with Chrome extensions, though
menus is preferred for Firefox-specific development as it
unlocks additional browser UI contexts.
2. Creating Context Menu Items
Menu items are created inside the extension's background script using
the browser.menus.create() method. This method accepts an
object that defines the item's properties, most notably its
id, title, and contexts.
browser.menus.create({
id: "search-selected-text",
title: "Search for '%s'",
contexts: ["selection"]
});Key properties include:
id: A unique string identifier for the menu item. This is required for identifying which item was clicked.title: The text displayed in the menu. Including%sin the string will automatically inject the user's currently selected text into the menu title.contexts: An array of strings specifying where the menu item should appear.type: Defines the behavior of the item. Options include"normal"(default),"checkbox","radio", and"separator".parentId: Used to nest an item inside an existing menu item, creating a submenu.
3. Targeting Specific Contexts
The contexts property prevents menu clutter by ensuring
custom actions only appear when relevant. The browser.menus
API supports standard web page contexts as well as Firefox-specific
browser UI contexts:
page: Appears when right-clicking anywhere on the web page that isn't a more specific element.selection: Appears only when the user highlights text.link: Appears when right-clicking a hyperlink.image,video,audio: Appears when right-clicking specific media elements.tab: A Firefox-specific context that adds the custom action when a user right-clicks a browser tab in the tab bar.bookmark: A Firefox-specific context that adds the action to right-clicked bookmarks in the toolbar or sidebar.
4. Handling Menu Clicks
Creating a menu item only displays it in the UI; it does not define
what happens when a user clicks it. To execute a custom action, the
background script must listen for the
browser.menus.onClicked event.
browser.menus.onClicked.addListener((info, tab) => {
if (info.menuItemId === "search-selected-text") {
const query = encodeURIComponent(info.selectionText);
browser.tabs.create({
url: `https://example.com/search?q=${query}`
});
}
});The listener function receives two parameters:
info: AnOnClickDataobject containing context data about the click. It includes themenuItemId, theselectionText(if text was highlighted), thelinkUrl(if a link was clicked), and thesrcUrl(if media was clicked).tab: Atabs.Tabobject representing the browser tab where the click occurred. This allows the extension to interact with that specific tab, such as injecting a script or reading its URL.
5. Updating and Removing Items Dynamically
Extensions can modify their context menu items in real time based on user actions or application state.
browser.menus.update(id, updateProperties): Changes the properties of an existing menu item, such as updating itstitleor toggling thecheckedstate of a checkbox item.browser.menus.remove(id): Deletes a specific menu item.browser.menus.removeAll(): Clears all context menu items created by the extension.browser.menus.onShown: An event that fires right before the context menu is displayed. Developers can use this event in combination withbrowser.menus.update()andbrowser.menus.refresh()to dynamically alter the menu based on the exact element the user right-clicked.