-
Notifications
You must be signed in to change notification settings - Fork 281
Fake Context Menu API
- Important notes
- Extra context menu items on tabs
- Add new item to the context menu on tabs
- Update existing item
- Remove existing item
- Remove all existing items
- Handle click event on menu item
(generated by Table of Contents Generator for GitHub Wiki)
-
On Firefox 64 and later, extra commands in the native tab context menu added by other addons are automatically imported to the tab context menu of TST's sidebar. You addon author don't need to do any special changes to integrate your addon to TST. There is a blog post describing technical details.
- The fake context menu is still available via a Ctrl-right-click on the sidebar, and it also appears when another addon Multiple Tab Handler triggers it after a tab-drag-selection action.
- All API message types were prefixed with
fake-
likefake-contextMenu-create
, but now they are unprefixed on TST 3.5.4 and later. Both prefixed and unprefixed versions are supported for backward compatibility, but I recommend you to use only unprefixed types. - This document assumes that you have experienced to develop one ore mroe Firefox extensions. If you've never done it, I recommend you to see the basic document for extensions authors.
On Firefox 63 and older, due to limitations of WebExtensions APIs, context menu on tabs is not available on custom tab bar in the sidebar panel.
(See also bug 1280347,
bug 1376251, and bug 1396031.)
Thus TST 2.0 provides its custom context menu in the sidebar.
Custom menu items added by browser.menus.create()
don't appear in the menu because it is just a fake.
Until any of bugs I listed above become fixed, your addon need to register its custom menu item to TST's fake context menu manually.
TST's fake context menu APIs are designed as a subset of the menus API of WebExtensions. You can support both Firefox's native menu and TST's fake menu with small changes.
New menu items can be added by a contextMenu-create
message.
It requires a parameter named params
, formatted as a createProperties
for the browser.menus.create()
.
You can share and reuse parameters for your context menu to both Firefox's menu and TST's menu.
For example:
const TST_ID = '[email protected]';
let params = {
id, type, title, parentId,
contexts: ['page', 'tab']
};
await browser.menus.create(params);
await browser.runtime.sendMessage(TST_ID, {
type: 'contextMenu-create',
params
}).catch(error => { /* TST is not available */ });
Only following parameters are available:
-
contexts
(onlytabs
works for TST) documentUrlPatterns
id
parentId
title
-
type
(normal
,checkbox
,radio
orseparator
.checkbox
andradio
are available on TST 2.4.25 and later.) -
enabled
(on TST 2.4.18 and later) -
icons
(on TST 2.4.18 and later) -
viewTypes
(on TST 3.5.4 and alter)
Both command
and onclick
are not supported by TST, so you need to use another API similar to browser.menus.onClicked
to do something for clicked menu items.
On TST 3.0.12 and later, added menu items won't be shown on a private window if your addon is not allowed for private windows.
The parameter viewTypes
is just for top level context menu items on your subpanel on TST 3.5.4 and later.
An existing (already created) menu item can be updated by a contextMenu-update
message.
It requires a parameter named params
, an array of parameters for the browser.menus.update()
.
You can share and reuse parameters for your context menu to both Firefox's menu and TST's menu.
For example:
let params = [
id,
{ title: "Updated Title" }
];
await browser.menus.update(...params);
await browser.runtime.sendMessage(TST_ID, {
type: 'contextMenu-update',
params
}).catch(error => { /* TST is not available */ });
On TST 2.4.25 or later, you can listen contextMenu-shown
and contextMenu-hidden
messages coressponding to browser.menus.onShown
and browser.menus.onHidden
, if you list them at the listeningTypes
parameter for the register-self
message. Please note that there is a difference: tab
s delivered to listeners are tree items, not tabs.Tab
objects. Here is an example:
let onMenuShown = async (info, tab) => {
// The `tab` is just a tree item, so you need to get full tab information manually.
tab = tab && await browser.tabs.get(tab.id);
let params = [
'togglePinned',
{ checked: tab && tab.pinned }
];
browser.menus.update(...params);
browser.menus.refresh();
browser.runtime.sendMessage(TST_ID, {
type: 'contextMenu-update',
params
}).catch(error => { /* TST is not available */ });
};
browser.menus.onShown.addListener(onMenuShown );
browser.runtime.onMessageExternal.addListener((message, sender) => {
switch (sender.id) {
case TST_ID:
switch (message.type) {
...
case 'contextMenu-shown':
// The `tab` is just a tree item, so you need to get full tab information manually.
browser.tabs.get(message.tab.id).then(tab => {
onMenuShown(message.info, tab);
});
break;
...
}
break;
}
});
On TST 3.0.12 and later, contextMenu-shown
and contextMenu-hidden
notifications won't be delivered if they happen on a private window and your addon is not allowed for private windows.
An existing menu item can be removed by a contextMenu-remove
message.
It requires a parameter named params
, a string of a menu item id for the browser.menus.remove()
.
You can share and reuse parameters for your context menu to both Firefox's menu and TST's menu.
For example:
let params = 'command-for-inactive-tab';
await browser.menus.update(params);
await browser.runtime.sendMessage(TST_ID, {
type: 'contextMenu-remove',
params
}).catch(error => { /* TST is not available */ });
All menu items added by your addon can be removed by a contextMenu-remove-all
message, at a time.
It doesn't accept any parameter - same to the browser.menus.removeAll()
.
For example:
await browser.menus.removeAll();
await browser.runtime.sendMessage(TST_ID, {
type: 'contextMenu-remove-all'
}).catch(error => { /* TST is not available */ });
When any added context menu is clicked, a contextMenu-click
message is notified to your addon via browser.runtime.onMessageExternal
.
The message has two properties info
(same to the first argument info
given to the listener of the browser.menus.onClicked
) and tab
(a tree items corresponding to the context tab) so you can process it by a common listener for browser.menus.onClicked
.
For example:
let onMenuItemClick = async (info, tab) => {
// The `tab` is just a tree item, so you need to get full tab information manually.
tab = tab && await browser.tabs.get(tab.id);
switch (info.menuItemId) {
case 'my-command':
// do something;
break;
}
};
browser.menus.onClicked.addListener(onMenuItemClick);
browser.runtime.onMessageExternal.addListener((message, sender) => {
switch (sender.id) {
case TST_ID:
switch (message.type) {
...
case 'contextMenu-click':
onMenuItemClick(message.info, message.tab);
break;
...
}
break;
}
});
This message will be delivered to your addon even if you don't list this at the listeningTypes
parameter for the register-self
message.
On TST 3.0.12 and later, this notification won't be delivered if it happens on a private window and your addon is not allowed for private windows.