Open Bug 1409262 Opened 3 years ago Updated 1 year ago

Updated openerTabId is not notified via tabs.onUpdated if it is changed by tabs.update()


(WebExtensions :: General, defect, P5)



(Not tracked)


(Reporter: yuki, Unassigned)


(Blocks 1 open bug)


(Whiteboard: [tabs][design-decision-approved])

The API document says that addon can change "tas.Tab"'s "openerTabId" by "tabs.update()". However, after I actually set new "openerTabId" for a tab, it is not notified.

Steps to reproduce:

 1. Open two tabs. For example, they have their own ID "1" and "2".
 2. Open debugger for a tab-related addon, like Tab Center Redux.
 3. Add a listener for tabs.onUpdated, like:
    browser.tabs.onUpdated.addListener((aTabId, aChangeInfo, aTab) => {
      console.log('tabs.onUpdated ', aTabId, aChangeInfo, aTab);
 4. Set the ID of one tab as "openerTabId" of another tab, like:
    browser.tabs.update(1, { opwnerTabId: 2 });

Actual result:
Nothing is reported in the console.

A message "tabs.onUpdated ..." is reported in the console.

Additional information:
Updated openerTabId is actually applied to the tab. You can confirm that by tabs.get(), like:
Looking at the code for this, I am not surprised that onUpdated is not fired when only the openerId of a tab is updated.

Do we think it should be? Piro, can you confirm if onUpdated fires in Chrome for a similar update?
Flags: needinfo?(yuki)
Hmm, actually Chrome also doesn't fire tabs.onUpdated for openerTabId. Firefox's current behavior is quite compatible to Chrome.

However I still think it should be notified via tabs.onUpdated (both Firefox and Chrome should do that) because some addon needs to know updated openerTabId immediately. For example, an addon "Tree Style Tab"(1) now uses openerTabId to save "parent tab" information for a tab, and another addon "Tab Session Manager"(2) saves/restores tabs with openerTabId. As the result, TST can restore tree of tabs for restored session based on openerTabId. Currently TSM periodically saves session information on every 15 minutes (by default), but because changes of openerTabId is not notified, TSM cannot save updated tree structure immediately.


Of course TST can send something message to already registered addons via runtime.sendMessage to notify "openerTabId is updated", but not all addons can do such explicit communication. There are possibly other tab tree addons and other session management addons. Moreover, there possibly other type addons using openerTabId. I think it is reasonable that such addons update itself immediately on tabs.onUpdated for openerTabId.
Flags: needinfo?(yuki)
Thanks for doing the research and updating the bug, Piro. I'm going to make this as design-decision-needed so we can decide if we want to support this or not.
Priority: -- → P5
Whiteboard: [tabs][design-decision-needed]
Hi Piro, this has been added to the agenda for the October 31, 2017 WebExtensions APIs triage meeting. Would you be able to join us on Vidyo or on IRC? 

Here's a few things about the triage to keep in mind: 

* We normally spend 5 minutes per bug
* The more information in the bug, the better
* The goal of the triage is to give a general thumbs up or thumbs down on a proposal; we won't be going deep into implementation details

Relevant Links: 

* Wiki for the meeting:
* Meeting agenda:
* Vision doc for WebExtensions:
OK, I hope to join the meeting on IRC. But it is AM2:30 in Japan, so I possibly miss it. Now I try to write more information for this.

There are three different viewpoints about this bug:

 1) Should openerTabId be updatable or should not?
 2) Which updatable attributes should be notified via tabs.onUpdated? All or only some of them?
 3) Is there any available workaround by addon authors?

1) Actually openedTabId is updatable on Google Chrome. So, to keep compatibility with Google Chrome, it still should be updatable. Otherwise, it becomes more hard to port extensions written for Chrome to Firefox.

2) I think this is the most important point on this bug. The API doc of tabs.onUpdated says that its listener will receive a "changeInfo" object, and changeInfo will have only some attributes:
(Actually "isArticle" and some other attributes are also notified - they are undocumented for now.)

On the other hand, tabs.update() receives "updateProperties" and an updateProperties also have only some attributes:

"tabs.Tab", "changeInfo" and "updateProperties" are similar but different. There are some groups of attributes:

A-1) Updatable / Notifiable (ex. url, pinned)
A-2) Updatable / Unnotifiable (ex. active, openerTabId, autoDiscardable)
B-1) Unupdatable / Notifiable  (ex. status, favIconUrl)
B-2) Unupdatable / Unnotifiable (ex. height, index)

A-1 and B-2 are simple. B-1 seems to be restricted by some reasons. For example title and favIconUrl strongly depend on tab content; that seems reasonable.

And there is a special group A-2, openerTabId is here. I think that attributes in A-2 must have something reason that it must not to be notified via tabs.onUpdated. Actually "active" is notified via tabs.onActivated, because (in my opinion) it is very special and should not handled by generic event tabs.onUpdated. However I couldn't imagine why other attributes "openerTabId" and "autoDiscardable" must not be notified. tabs.Tab also have these attributes, and they don't depend on tab content, so I think it seems reasonable that they are also notified via tabs.onUpdated.
3) This is also important. If there is any workaround to track updated "openerTabId" immediately, there is less reason that "openerTabId" is notified via tabs.onUpdated.

After my experiments, conclusion: it is impossible by addon to know that "openerTabId" is updated by other addon or not.

If it is updated by the addon itself, it can be tracked by self. Actually an example Tree Style Tab addon does it, like:

function attachTabTo(child, parent) {
  child.apiTab.openerTabId =; // ".apiTab" is a tabs.Tab
  // Cache the last value updated by self.
  // If tabs.Tab's openerTabId is different from this value,
  // that means: openerTabId is changed by any other addon.
  child.apiTab.TSTUpdatedOpenerTabId = child.apiTab.openerTabId;
  browser.tabs.update(, { openerTabId: });

However, tabs.Tab's openerTabId is possibly modified by any other addon. If it is updated by someone, it isn't notified via tabs.onUpdated and an addon which uses openerTabId will know the change suddenly on different timing: when the addon tries to get tab information by browser.tabs.get(), when the addon tracks updated attributes of a tab by tabs.onUpdated (the listener receives complete tabs.Tab object as its third argument and it will have updated openerTabId), and others. Because most WebExtensions APIs are asynchronous, the workaround above is not effective to detect whether the openerTabId is updated by self or by others. Before tabs.onUpdated is notified by the above code, any other addon can change the tab's openerTabId andthe listener for tabs.onUpdate will receive changed "status" or something together with the third argument tabs.Tab including modified openerTabId. As the result, the workaround above won't work as expected. The scenario is:

 1) Someone changes the tab's openerTabId to 11 asynchronously.
 2) My addon changes the tab's openerTabId to 10 asynchronously.
    The cached TSTUpdatedOpenerTabId also becomes to 10.
 3) tabs.onUpdated is notified for 1).
    My addon's listener compares TSTUpdatedOpenerTabId(10) with notified openerTabId(11).
    My addon detects that it is changed by others.
    TSTUpdatedOpenerTabId is updated to 11.
 4) tabs.onUpdated is notified for 2).
    My addon's listener compares TSTUpdatedOpenerTabId(11) with notified openerTabId(10).
    My addon wrongly detects that it is changed by others, but actually it was done by self.
Thus, if openerTabId is not notified via tabs.onUpdated, I think that addon authors must give up tracking of dynamically changed openerTabId. instead addon authors always need to scan all tabs and their openerTabId, to know complete relation information of tabs. Such periodical tasks can eat more computing resources. In other words, tabs.onUpdated for openerTabId will reduce such an oxygen thief processes.
Flags: needinfo?(bob.silverberg)
It was decided that we should diverge from Chrome's behaviour here and notify via onUpdated when openerTabId changes. Approved.
Flags: needinfo?(bob.silverberg)
Whiteboard: [tabs][design-decision-needed] → [tabs][design-decision-approved]
If FF could notify when openerTabId changes, it would help the compatibility cross extension. Now, when I changed openerTabId value in my extension, tree style tab extension can't know it and thus can't update itself.

Any progress about it ?
Product: Toolkit → WebExtensions
Blocks: 1476144
You need to log in before you can comment on or make changes to this bug.