API for other addons

YUKI "Piro" Hiroshi edited this page Aug 28, 2018 · 79 revisions

This describes about Tree Style Tab 2.x API for other WebExtensions-based addons. See also old documentation about Legacy TST 0.19.x (Japanese translation)

(generated by Table of Contents Generator for GitHub Wiki)

Abstract

To communicate with TST, your addon can send messages to TST via browser.runtime.sendMessage(). You need to specify TST's internal ID treestyletab@piro.sakura.ne.jp as the first argument of the method.

Any API message for TST is an object with a string property named type, which indicates the type of the message. For example:

const kTST_ID = 'treestyletab@piro.sakura.ne.jp';
var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'register-self',
  name: 'My Addon',1
  icons: browser.runtime.getManifest().icons,
  listeningTypes: ['tab-mousedown', 'tab-mouseup']
});

You'll receive returned value from TST APIs as a promise.

Register and unregister your addon to TST

Register and unregister

You need to register your addon to TST, to receive notification messages from TST. Send a message with the type register-self to TST, like:

async function registerToTST() {
  try {
  var success = await browser.runtime.sendMessage(kTST_ID, {
    type: 'register-self',
    // The name of your addon (string, optional)
    name: browser.i18n.getMessage('extensionName'),
    // Icons (used for extra context menu items)
    icons: browser.runtime.getManifest().icons, // { '16': '/path/to/icon.png', 24: '...', ... }
    // The list of listening message types (array of string)
    listeningTypes: ['tab-mousedown', 'tab-mouseup'],
    // Extra style rules applied in the sidebar (string, optional)
    style: `
      .tab.unread {
        color: red;
      }
    `
  });
  }
  catch(e) {
    // TST is not available
  }
}
registerToTST();

The returned promise will be filled with a boolean value true, when TST successfully process the message.

When you addon is loaded and initialized before TST is initialized, no one responds to the message and you'll fail to register your addon. Because TST cannot broadcast any message to unknown addons, your addon won't receive any message from TST until it is successfully registered. So the user need to reload your addon manually if he install TST after your addon.

TST caches IDs of known registered addons and sends a message ready to them when TST is successfully initialized. For secondary and after startup cases, you should listen the message to re-register your addon safely, like:

browser.runtime.onMessageExternal.addListener((aMessage, aSender) => {
  switch (aSender.id) {
    case kTST_ID:
      switch (aMessage.type) {
        ...
        case 'ready':
          registerToTST(); // passive registration for secondary (or after) startup
          break;
        ...
      }
      break;
  }
});
registerToTST(); // aggressive registration on initial installation

After your addon is successfully registered, it will receive messages from TST via the event listener registered to browser.runtime.onMessageExternal. Note that you should keep listening the ready message from TST even if you successfully registered your addon, because you need to re-register your addon again when TST is reloaded while your addon is working.

The icons parameter works only on Tree Style Tab 2.4.18 or later.

Note for Tree Style Tab 2.4.17 and later: You should list message types only your addon really requires, via the listeningTypes parameter. Otherwise, TST may change some behaviors of itself to wait responses from external addons. For backward compatibility, all known type messages on TST 2.4.16 (ready, shutdown, tab-clicked, tab-mousedown, tab-mouseup, tabbar-clicked, tabbar-mousedown, and tabbar-mouseup) will be delivered to your addon if you omit this parameter.

To unlisten events, you need to send unregister-self message from your addon:

var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'unregister-self'
});

Uninit special features for TST when TST is going to be disabled

This API is available on TST 2.0.3 or later.

By limitations of WebExtensions APIs, TST cannot send something messages like "shutdown" to listeners when it is going to be disabled (and uninstalled). If your addon provides something special feature for TST, it won't work after TST is disabled dynamically. Thus you'll need something way to know that TST is still alive or not.

ping is available for this purpose. If you send a message with the type ping, TST simply returns true as the result. On the other hand, if TST is not available, browser.runtime.sendMessage() will report an error. By these difference you can know TST's living status. For example:

function checkTSTAvailability() {
  try {
    await browser.runtime.sendMessage(kTST_ID, {
      type: 'ping'
    });
  }
  catch(e) {
    clearInterval(checkTSTAvailability.timer);
    uninitFeaturesForTST();
  }
}
checkTSTAvailability.timer = setInterval(checkTSTAvailability, 10000);

Extra context menu items on tabs

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.

Add new item to the context menu on tabs

New menu items can be added by a fake-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:

let params = {
  id, type, title, parentId,
  contexts: ['page', 'tab']
};
await browser.menus.create(params);
await browser.runtime.sendMessage(kTST_ID, {
  type: 'fake-contextMenu-create',
  params
}).catch(error => { /* TST is not available */ });

Only following parameters are available:

  • contexts (only tabs works for TST)
  • documentUrlPatterns
  • id
  • parentId
  • title
  • type (normal, checkbox, radio or separator. checkbox and radio are available on TST 2.4.25 or later.)
  • enabled (on Tree Style Tab 2.4.18 or later)
  • icons (on Tree Style Tab 2.4.18 or later)

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.

Update existing item

An existing (already created) menu item can be updated by a fake-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(kTST_ID, {
  type: 'fake-contextMenu-update',
  params
}).catch(error => { /* TST is not available */ });

On TST 2.4.25 or later, you can listen fake-contextMenu-shown and fake-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. Here is an example:

var onMenuShown = (aInfo, aTab) => {
  let params = [
    'togglePinned',
    { checked: aTab.pinned }
  ];
  await browser.menus.update(...params);
  await browser.runtime.sendMessage(kTST_ID, {
    type: 'fake-contextMenu-update',
    params
  }).catch(error => { /* TST is not available */ });
};
browser.menus.onShown.addListener(onMenuShown );
browser.runtime.onMessageExternal.addListener((aMessage, aSender) => {
  switch (aSender.id) {
    case kTST_ID:
      switch (aMessage.type) {
        ...
        case 'fake-contextMenu-shown':
          onMenuShown(aMessage.info, aMessage.tab);
          break;
        ...
      }
      break;
  }
});

Remove existing item

An existing menu item can be removed by a fake-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(kTST_ID, {
  type: 'fake-contextMenu-remove',
  params
}).catch(error => { /* TST is not available */ });

Remove all existing items

All menu items added by your addon can be removed by a fake-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(kTST_ID, {
  type: 'fake-contextMenu-remove-all'
}).catch(error => { /* TST is not available */ });

Handle click event on menu item

When any added context menu is clicked, a fake-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 (same to the second argument tab) so you can process it by a common listener for browser.menus.onClicked. For example:

var onMenuItemClick = (aInfo, aTab) => {
  switch (aInfo.menuItemId) {
    case 'my-command':
      // do something;
      break;
  }
};
browser.menus.onClicked.addListener(onMenuItemClick);
browser.runtime.onMessageExternal.addListener((aMessage, aSender) => {
  switch (aSender.id) {
    case kTST_ID:
      switch (aMessage.type) {
        ...
        case 'fake-contextMenu-click':
          onMenuItemClick(aMessage.info, aMessage.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.

Manipulate tree of tabs

Basics to specify tabs

Most of TST's APIs accept tabs.Tab.id or some alias name to specify target tabs. Available aliases are:

  • current / active: the active tab in the last focused window.
  • next: the next tab of the active tab.
  • nextSibling: the next sibling tab of the active tab.
  • previous / prev: the previous tab of the active tab.
  • previousSibling / prevSibling: the previous sibling tab of the active tab.
  • senderTab: the tab containing the content script which calls the API. (available on TST 2.4.9 and later)

Note: alias names are available on TST 2.4.4 and later.

Open new child tab from a specific tab

To open new child tab from any existing tab, you just need to specify openerTabId option (available at Firefox 57 and later) for browser.tabs.create(). For example:

var [activeTab, ] = await browser.tabs.query({
  active: true,
  currentWindow: true
});
browser.tabs.create({
  url: 'http://www.example.com/',
  openerTabId: activeTab.id // optional, tabs.Tab.id
});

Indent (demote) tab

This API is available on TST 2.4.4 or later.

indent (and demote) message attaches the specified tab to its previous sibling tab. For example:

var success = await browser.runtime.sendMessage(kTST_ID, {
  type:           'indent', // or 'demote'
  tab:            'current', // required, tabs.Tab.id or alias
  followChildren: false // optional, boolean (default=false)
});

If you specify an option followChildren:true, all of descendants are indented together. Otherwise descendants are detached from the specified tab and only the tab is indented.

Outdent (promote) tab

This API is available on TST 2.4.4 or later.

outdent (and promote) message attaches the specified tab to its grand-parent tab. For example:

var success = await browser.runtime.sendMessage(kTST_ID, {
  type:           'outdent', // or 'promote'
  tab:            'current', // required, tabs.Tab.id or alias
  followChildren: false // optional, boolean (default=false)
});

If you specify an option followChildren:true, all of descendants are outdented together. Otherwise descendants are detached from the specified tab and only the tab is outdented.

Attach existing tab to another as a child

attach message attaches an existing tab to different tab as its child. For example:

var success = await browser.runtime.sendMessage(kTST_ID, {
  type:         'attach',
  parent:       6, // required, tabs.Tab.id or alias
  child:        9, // required, tabs.Tab.id or alias
  insertBefore: 8, // optional, tabs.Tab.id or alias
  insertAfter:  7, // optional, tabs.Tab.id or alias
});

If the new child tab is already attached to different parent, then it is implicitly detached from its old parent.

You can give optional parameter insertBefore and/or insertAfter to control where the attached tab is placed at. Otherwise the attached tab will be placed at top or bottom of existing children.

Detach existing child tab from its parent

detach message detaches a child tab from its parent. For example:

var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'detach',
  tab:  9 // required, tabs.Tab.id or alias
});

Note that detached tab (and its descendants) stays there. In other words, if you detach a child tab from a tree, you must move detached tab (and its descendants) to somewhere like after the last tab manually.

Collapse expanded tree

collapse-tree message collapses an existing tree.

var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'collapse-tree',
  tab:  2 // required, tabs.Tab.id or alias
});

It always succeeds if the tab has no child or it is already collapsed.

Expand collapsed tree

expand-tree message expands an existing tree.

var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'expand-tree',
  tab:  2 // required, tabs.Tab.id or alias
});

It always succeeds if the tab has no child or it is already expanded.

Move tree to different position

There is no specific API to move tree of tabs to different position. Please use browser.tabs.move() simply to move tree of tabs.

  • When a parent tab is moved in same window, all descendant tabs are also moved together automatically.
  • When a parent tab is moved across windows, all descendant tabs are left in the source window. In this case, if you hope that a whole tree is moved to different window, then you need to move descendant tabs to the destination window and restructure tree manually.

On TST 2.4.4 and later, there are more special APIs to move tabs on the tree: move-up and move-down. These APIs accept an optional parameter followChildren (it's false by default) so they will help you to move a parent tab without its children, like:

var success = await browser.runtime.sendMessage(kTST_ID, {
  type:           'move-up',
  tab:            'current', // required, tabs.Tab.id or alias
  followChildren: false // optional, boolean (default=false)
});

var success = await browser.runtime.sendMessage(kTST_ID, {
  type:           'move-down',
  tab:            'current', // required, tabs.Tab.id or alias
  followChildren: false // optional, boolean (default=false)
});

Focus to the next/previous sibling tab

This API is available on TST 2.4.4 or later.

focus message focuses to the specified tab. For example:

var success = await browser.runtime.sendMessage(kTST_ID, {
  type:     'focus',
  tab:      'nextSibling', // required, tabs.Tab.id or alias
  silently: false // optional, boolean (default=false)
});

The tab parameter accepts alias name of tabs, so nextSibling will focus to the next sibling tab, previousSibling will focus to the previous sibling tab.

If you specify an option silently:true, children of focused tab will be kept collapsed. Otherwise TST expands the tree of focused tab automatically.

Duplicate tab as child/sibling tab

This API is available on TST 2.4.4 or later.

duplicate message duplicates the specified tab at the specified position. For example:

var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'duplicate',
  tab:  'current', // required, tabs.Tab.id or alias
  as:   'child' // optional, string
});

Here is the list of available value for the as option:

  • sibling: duplicated tab will be placed just next to the source tab.
  • nextSibling: duplicated tab will be placed as the next sibling of the source tab.
  • child: duplicated tab will be placed as a child of the source tab.
  • orphan (default): duplicated tab will be placed at the end of the tab bar.

Create new group from given tabs

This API is available on TST 2.4.4 or later.

group-tabs message creates a new tree from specified tabs. Tabs will be grouped under a dummy parent tab. For example:

var parentTab = await browser.runtime.sendMessage(kTST_ID, {
  type: 'group-tabs',
  tabs: [1, 2, 3] // required, array of tabs.Tab.id or alias
});

Close whole tree

There is no specific API to close all tabs in a tree by just one operation. Please use browser.tabs.remove() simply to close tree of tabs.

  • When a closing parent tab has collapsed children, all descendants are also closed together automatically.
  • When a closing parent tab has expanded children, the first child tab is promoted as the new parent. In this case, if you hope that a whole expanded tree is closed, then you need to collapse the tree at first or close all descendant tabs manually.

Scroll the tab bar

This API is available on TST 2.0.2 or later.

scroll message scrolls the tab bar.

var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'scroll',
  ...
});

There are three forms of its usage:

  • Scrolling to a tab. In this form, you must specify an ID of a tab, like:

    var success = await browser.runtime.sendMessage(kTST_ID, {
      type: 'scroll',
      tab:  2 // integer, an ID of a tab
    });

    Note that this does nothing if the specified tab is already visible.

  • Scrolling to absolute position. In this form, you must specify an ID of a window and absolute position, like:

    var success = await browser.runtime.sendMessage(kTST_ID, {
      type:     'scroll',
      window:   3,  // integer, an ID of a window
      position: 250 // integer, an absolute scroll position in pixels
    });
  • Scrolling by relative delta In this form, you must specify an ID of a window and delta, like:

    var success = await browser.runtime.sendMessage(kTST_ID, {
      type:   'scroll',
      window: 3,  // integer, an ID of a window
      delta:  -20 // integer, a relative scroll in pixels
    });

Get tree information

Data format

TST API provides ability to get tree information. Tree of tabs are presented as a form of extended tabs.Tab. Each tab has two extra properties states and children.

  • states is an array of class names applied to the tab.
  • indent is the indent level of the tab (integer). It is 0 for top level tabs. (Note: this property is available on Tree Style Tab 2.4.8 and later.)
  • children is an array of child tabs with same format (extended tabs.Tab) recursively.
  • ancestorTabIds is an array of ancestor tabs' tabs.Tab.id (integer). (Note: this property is available on Tree Style Tab 2.4.17 and later.)

For example:

{ id: 2,
  title: "Tab B",
  url: "...",
  ...
  states: ["active", "complete"],
  indent: 0,
  children: [
    { id: 3,
      title: "Tab B-a",
      ...
      states: ["complete"],
      indent: 1,
      children: [],
      ancestorTabIds: [2] },
    { id: 4,
      title: "Tab B-b",
      ...
      states: ["subtree-collapsed", "complete"],
      states: ["complete"],
      indent: 1,
      children: [
        { id: 5,
          title: "Tab B-b-1",
          ...
          states: ["collapsed", "complete"],
          indent: 2,
          children: [],
          ancestorTabIds: [2, 4] }
      ],
      ancestorTabIds: [2] }
  ],
  ancestorTabIds: [] }

Here is a list of major classes appeared in states:

  • active: Same to tabs.Tab.active.
  • audible: Same to tabs.Tab.audible.
  • collapsed: The tab is in a collapsed subtree. The tab is invisible.
  • complete: Same to tabs.Tab.status == "complete".
  • discarded: Same to tabs.Tab.discarded.
  • incognito: Same to tabs.Tab.incognito.
  • loading: Same to tabs.Tab.status == "loading".
  • muted: Same to tabs.Tab.mutedInfo.muted.
  • pinned: Same to tabs.Tab.pinned.
  • subtree-collapsed: The tab has any child, and its subtree is collapsed. All child tabs are invisible.
  • group-tab: A special class on a dummy tab for grouping.

APIs to get tree information

There are an API get-tree, to collect tab information with their tree structure. For descriptions, now we assume that there a set of tabs with tree structure:

  • Window A (id:1)
    • Tab A (id:1, pinned)
    • Tab B (id:2, active)
      • Tab B-a (id:3)
      • Tab B-b (id:4, collapsed)
        • Tab B-b-1 (id:5)
    • Tab C (id:6, collapsed)
      • Tab C-a (id:7)

Get tree information for specific single tab

You should give the ID of a tab via the tab parameter, to get tree information of single tab. For example:

var tab = await browser.runtime.sendMessage(kTST_ID, {
  type: 'get-tree',
  tab:  2
});
/* tab =>
{ id: 2, ...
  states: ["active", "complete"],
  children: [
    { id: 3, ...
      states: ["complete"],
      children: [],
      ancestorTabIds: [2] },
    { id: 4, ...
      states: ["subtree-collapsed", "complete"],
      children: [
        { id: 5, ...
          states: ["collapsed", "complete"],
          children: [],
          ancestorTabIds: [2, 4] }
      ],
      ancestorTabIds: [2] }
  ],
  ancestorTabIds: [] }
*/

Get tree information for specific multiple tabs

You should give an array of IDs of tabs via the tabs parameter, to get tree information of multiple tab at a time. For example:

var tabs = await browser.runtime.sendMessage(kTST_ID, {
  type: 'get-tree',
  tabs:  [1, 2]
});
/* tabs =>
[
  { id: 1, ...
    states: ["pinned", "complete"],
    children: [] },
  { id: 2, ...
    states: ["active", "complete"],
    children: [...] }
]
*/

Get tree information for all tabs in a specific window

You should give an window ID via the window parameter, to get clear tree information of a window at a time. For example:

var tabs = await browser.runtime.sendMessage(kTST_ID, {
  type:   'get-tree',
  window: 1
});
/* tabs =>
[
  { id: 1, ... },
  { id: 2, ...
    children: [
      { id: 3, ... },
      { id: 4, ...
        children: [
          { id: 5, ... }
        ] }
    ] },
  { id: 6, ...
    children: [
      { id: 7, ... }
    ] }
]
*/

Note that only root tabs appear in the array (id=1, 2, 6). As the result, you need to scan children of each tab to retrieve all tabs. If you hope to get a flat list of all tabs in the current window, see the next section.

Get tree information for all tabs in a window, as a flat array

You should give a string * via tab or tabs parameter, to get tree information of all tabs at a time as a flat array. For example:

var tabs = await browser.runtime.sendMessage(kTST_ID, {
  type:   'get-tree',
  window: 1,
  tabs:   '*'
});
/* tabs =>
[
  { id: 1, ... },
  { id: 2, ...
    children: [
      { id: 3, ... },
      { id: 4, ...
        children: [
          { id: 5, ... }
        ] }
    ] },
  { id: 3, ... },
  { id: 4, ...
    children: [
      { id: 5, ... }
    ] },
  { id: 5, ... },
  { id: 6, ...
    children: [
      { id: 7, ... }
    ] },
  { id: 7, ... }
]
*/

Note that some tabs appear multiple times (id=3, 4, 5, 7). This is because the wildcard * always collects tree information from all tabs. If you don't need such duplicated information, see the previous section.

If you omit the window parameter, tabs in the last focused window will be returned.

Override reaction for mouse wheel rotation on the vertical tab bar

By default, mouse wheel simply scrolls the tab bar. If you hope to override the behavior, you need to lock the scroll and do something based on notified messages.

Stop and restart scrolling of the tab bar

This API is available on TST 2.0.2 or later.

scroll-lock message disables the default scrolling behavior.

var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'scroll-lock'
});

On the other hand, scroll-unlock message enables the default scrolling behavior again.

var success = await browser.runtime.sendMessage(kTST_ID, {
  type: 'scroll-unlock'
});

Multiple addons can lock the scroll at a time, and TST never produce the default scrolling behavior while it is locked by any addon even if your addon already unlocks. In other words, you must not forget to unlock the scroll before your addon is completely unloaded (disabled or uninstalled).

Messages notified by mouse wheel rotation

This API is available on TST 2.0.2 or later.

While your addon locks the scrolling, TST notifies scroll message to your addon.

browser.runtime.onMessageExternal.addListener((aMessage, aSender) => {
  switch (aSender.id) {
    case kTST_ID:
      switch (aMessage.type) {
        ...
        case 'scrolled':
          // do something here. for example:
          let tab = getNextFocusedTab(aMessage.tabs);
          browser.tabs.update(tab.id, { active: true });
          return Promise.resolve(true); // you must return any non-undefined value.
        ...
      }
      break;
  }
});

Here is a list of properties notified message have:

  • tab: An extended tabs.Tab for the tab you rotated the mouse wheel on.
  • tabs: A flatten array of extended tabs.Tabs in the window. This quite equals to the result of get-tree with tabs:'*'.
  • window: An integer, the owner window's ID.
  • deltaY: A number, the value of WheelEvent#deltaY.
  • deltaMode: An integer, the value of WheelEvent#deltaMode.
  • scrollTop: An integer, the current scroll position of the tab bar.
  • scrollTopMax: An integer, the maximum scroll position of the tab bar.
  • altKey: A boolean, the Alt modifier key is pressed or not.
  • ctrlKey: A boolean, the Ctrl (Control) modifier key is pressed or not.
  • metaKey: A boolean, the Meta (Command on macOS) modifier key is pressed or not.
  • shiftKey: A boolean, the Shift modifier key is pressed or not.
  • clientX: An integer, the value of MouseEvent#clientX indicating the coordinate the event fired at.
  • clientY: An integer, the value of MouseEvent#clientY indicating the coordinate the event fired at.

Based on these information, you'll scroll the tab bar with custom algorythm or any other reactions.

You must return any non-undefined value (including false, 0, and so on) from the listener. Otherwise TST guesses the listener addon is already unloaded and unlocks the scroll for your addon automatically.

APIs to set custom state for tabs

You can set custom state to tabs via messages with add-tab-state and remove-tab-state type. Custom classes will appear as classes of tab elements like <li class="tab active myaddon-marked">, so you can apply any style definitions to tabs.

Note that all built-in states and custom states are mixed into the same namespace, so you can break TST's functions easily if you modify TST's built-in states. For safety, prefixed names like myaddon-marked instead of simple names like marked are recommended.

Add state(s)

A message with the type add-tab-state adds given states to specified tabs as their classes. For example:

browser.runtime.sendMessage(kTST_ID, {
  type:  'add-tab-state',
  tabs:  [1, 2, 3], // required, an array of tabs.Tab.id or alias
  state: 'selected' // required, a state string or an array of state strings
});

You can specify multiple states at a time:

browser.runtime.sendMessage(kTST_ID, {
  type:  'add-tab-state',
  tabs:  [1, 2, 3],
  state: ['selected', 'custom-status']
});

Remove state(s)

A message with the type remove-tab-state removes given states from specified tabs. For example:

browser.runtime.sendMessage(kTST_ID, {
  type:  'remove-tab-state',
  tabs:  [1, 2, 3], // required, an array of tabs.Tab.id or alias
  state: 'selected' // required, a state string or an array of state strings
});

You can specify multiple states at a time:

browser.runtime.sendMessage(kTST_ID, {
  type:  'remove-tab-state',
  tabs:  [1, 2, 3],
  state: ['selected', 'custom-status']
});

Notification messages from TST

TST sends notification messages to registered addons. To receive these messages, you need to register your addon at first.

When the TST itself is initialized

A message with the type ready will be notified, when the TST itself is initialized. For more details, see another section: how to register your addon.

When the TST sidebar is shown/hidden

This API is available on TST 2.4.23 or later.

There are two notification message types: sidebar-show and sidebar-hide.

  • A message with the type sidebar-show will be notified when the TST sidebar is shown.
  • A message with the type sidebar-hide will be notified when the TST sidebar is hidden.

Here is a list of properties these type message objects commonly have:

  • window: An integer, the owner window's ID for the sidebar.

When the current tab is closed

If your addon provides something feature to control focusing of tabs for closed current tab, you can prevent TST's behavior. In other words, if no one prevents TST's behavior, TST will switch tab focus to something suitable when the current tab is closed.

A message with the type try-move-focus-from-closing-current-tab will be notified, when the current tab is going to be closed. Here is a list of properties the message object has:

If any addon responds to the message with a boolean value true, TST's default behavior (activating the next sibling or the parent tab) will be canceled. For example:

browser.runtime.onMessageExternal.addListener((aMessage, aSender) => {
  switch (aSender.id) {
    case kTST_ID:
      switch (aMessage.type) {
        ...
        case 'try-move-focus-from-closing-current-tab':
          let focusChanged = ...; // you'll do something here
          return Promise.resolve(focusChanged);
        ...
      }
      break;
  }
});

When any context menu item is clicked

When a context menu item added by your addon is clicked, your addon will receive a notification message with the type fake-contextMenu-click. For more details, see another section.

This message will be delivered to your addon even if you don't list this at the listeningTypes parameter for the register-self message.

When the context menu is opened and closed

This API is available on TST 2.4.25 or later.

A message with the type fake-contextMenu-shown will be notified, when the context menu is going to be opened. It corresponds to the browser.menus.onShown. See another section for more details.

And, another message with the type fake-contextMenu-hidden will be notified, when the context menu is closed. It corresponds to the browser.menus.onHidden.

These type messages won't be delivered to your addon implicitly. You need to list them at the listeningTypes parameter for the register-self message.

When a tab is clicked

Messages with tab-mousedown, tab-mouseup and tab-clicked types will be notified, when any tab is clicked. Here is a list of properties the message object has:

  • tab: An extended tabs.Tab for the clicked tab.
  • window: An integer, the owner window's ID.
  • button: An integer to indicate the clicked button. 0=left button, 1=middle button (2 won't be notified)
  • ctrlKey: A boolean, the Ctrl (Control) modifier key is pressed or not.
  • shiftKey: A boolean, the Shift modifier key is pressed or not.
  • altKey: A boolean, the Alt modifier key is pressed or not.
  • metaKey: A boolean, the Meta (Command on macOS) modifier key is pressed or not.
  • closebox: A boolean, the event happens on the closebox or not.
  • soundButton: A boolean, the event happens on the mute/unmute button or not. (This property is available on TST 2.5.3 or later.)

If any addon responds to the message with a boolean value true, TST's default behavior (activating the tab) will be canceled. For example:

browser.runtime.onMessageExternal.addListener((aMessage, aSender) => {
  switch (aSender.id) {
    case kTST_ID:
      switch (aMessage.type) {
        ...
        case 'tab-clicked':
          let focusChanged = ...; // you'll do something here
          return Promise.resolve(focusChanged);
        ...
      }
      break;
  }
});

When the non-tab area is clicked

A message with the type tabbar-clicked will be notified, when the non-tab area is clicked. Here is a list of properties the message object has:

  • window: An integer, the owner window's ID.
  • button: An integer to indicate the clicked button. 0=left button, 1=middle button (2 won't be notified)
  • isMiddleClick: A boolean indicating if a middle click was performed.
  • ctrlKey: A boolean, the Ctrl (Control) modifier key is pressed or not.
  • shiftKey: A boolean, the Shift modifier key is pressed or not.
  • altKey: A boolean, the Alt modifier key is pressed or not.
  • metaKey: A boolean, the Meta (Command on macOS) modifier key is pressed or not.

If any addon responds to the message with a boolean value true, TST's default behavior (add new tab) will be canceled. (TST 2.0.5 or later)

When the pointer is moved over tabs

This API is available on TST 2.4.19 or later.

Following type messages can be delivered to your addon by moving pointer over tabs:

  • tab-mousemove corresponds to mousemove event on tabs.
  • tab-mouseover corresponds to mouseover event on tabs. This won't be delivered again and again for same tab.
  • tab-mouseout corresponds to mouseout event on tabs. This won't be delivered again and again for same tab.

Here is a list of properties these type message objects commonly have:

  • window: An integer, the owner window's ID.
  • tab: An extended tabs.Tab for the clicked tab.
  • ctrlKey: A boolean, the Ctrl (Control) modifier key is pressed or not.
  • shiftKey: A boolean, the Shift modifier key is pressed or not.
  • altKey: A boolean, the Alt modifier key is pressed or not.
  • metaKey: A boolean, the Meta (Command on macOS) modifier key is pressed or not.
  • dragging: A boolean, a dragging operation (started by long-press) is in progress or not.

These type messages won't be delivered to your addon implicitly. You need to list them at the listeningTypes parameter for the register-self message.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.