Treestyletab: New tab from outside Firefox opens always as independent

Created on 10 Jan 2021  ·  23Comments  ·  Source: piroor/treestyletab

Short description

No matter what setting I choose for "New tab from outside Firefox", it (almost) always opens as an independent tab at the bottom of the tab sidebar.

Steps to reproduce

  1. Start Firefox with clean profile.
  2. Install TST.
  3. Choose "New tab from outside Firefox: the next sibling of the current tab", or child, etc.
  4. Open some tabs, then focus one that is not the last one.
  5. Open a link from an external application like Thunderbird.

Expected result

The tab will open as the next sibling, or child, etc.

Actual result

The tab opens always as an independent tab at the end of all tabs.
There is an error message: DataCloneError: The object could not be cloned. ExtensionChild.jsm:813
If I choose "child", maybe one time out of ten it will open as a child. The rest of the times it's independent, or the same as "no control".

Environment

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:84.0) Gecko/20100101 Firefox/84.0

  • Platform (OS): macOS 10.14.6
  • Version of Firefox: 84.0.2
  • Version (or revision) of Tree Style Tab: 3.6.5
platform specific

All 23 comments

I've successfully reproduced this problem with both TST 3.6.4 and TST 3.6.5 on macOS. It looks a platform specific problem. TST tries to detect "a new tab opened from another application" with this method:

  • When an external application is active, no Firefox window has a focus. A listener of browser.windows.onFocusChanged will receive -1 as the focused window ID when all Firefox window lost focus. TST memorizes this status. ( https://github.com/piroor/treestyletab/blob/d4087361bef6025828d99eb3bb493d8266a61e43/webextensions/background/api-tabs-listener.js#L1073 )
  • When a new tab is opened, TST checks that there is any focused Firefox window. If there is no focused window, TST treats the tab as "opened by an external application". ( https://github.com/piroor/treestyletab/blob/d4087361bef6025828d99eb3bb493d8266a61e43/webextensions/background/api-tabs-listener.js#L338 )

On Windows 10 browser.tabs.onCreated listeners are always called before browser.windows.onFocused listeners, thus the detection logic works as expected. However, on macOS the order of events is inverted: browser.tabs.onCreated listeners are called after browser.windows.onFocused listeners. As the result the detection logic unexpectedly detect new tabs as "opened from Firefox inside" always on macOS. Hmm...

After more research I've realized that this can't be solved on TST side.

  • A possible workaround based on a delay will affect to other unexpected cases. If TST treat a browser.tabs.onCreated event notified just after browser.windows.onFocused within 200 msec, it will detect a new tab opened via the "+" button on the tab bar in an inactive window as "opened by external application".
  • The order of both notifications browser.tabs.onCreated and browser.windows.onFocused won't be stabilized across platforms by Firefox side, because the current behavior is quite compatible to Google Chrome. Chrome also calls chrome.windows.onFocused listeners before chrome.tabs.onCreated listeners, on macOS.

I think I need to disable the unavailable option on macOS to reduce confusion.

@piroor just a friendly reminder on this one.

For now, I have set "guess a newly opened tab" to "about:blank", so that it follows the setting for that. I had to set Firefox Home preferences to Blank Page for Firefox's new tab button to work. I'm not sure yet if it will cause other problems.

I would be happy if there was a setting for _all_ tabs that were not opened or duplicated from another tab, including bookmarks etc. Because I often have 50-100 tabs in a window, I prefer new tabs to open nearby. Usually it's related to what I'm doing, and I don't want to get lost by going to the end of the tab bar. I tried setting browser.tabs.insertAfterCurrent - it's almost what I want, but it makes it always the first child. It also makes new blank tabs be the first child, regardless of the settings. I would like to set both to be the next sibling instead.

Would it be possible for TST to adjust the behaviour of browser.tabs.insertAfterCurrent so that instead of only first child, it could be sibling or next sibling?

OK, I've added a new expert option "Tabs from any other trigger" under the "New Tabs Behavior" section, with commits 844bb7074a2871c0ab25598178e9a2b042aa30d1 and 0869cade7fef03dea3f18657a42da7ab42af7077.

This will be a good solution for me, thank-you!

One thing I notice though, is that "undo close tab" now follows that setting. I expected that a closed tab would be restored in the same place it was before, which is also the behaviour with browser.tabs.insertAfterCurrent.

@piroor thanks again for adding the new "Tabs from any other trigger" option. I'm just hoping it would be possible to change it to match the behaviour of browser.tabs.insertAfterCurrent, so that "undo close tab" would still restore to where it was previously, rather than to the setting of the new option.

What I'm trying to avoid is tabs opening at the very end of the tab (side)bar, when it's unknown where else to put them. If it _is_ known, i.e. if it's related to another tab or it was closed and re-opened, then it should go there.

Such a restored tab has its original tree structure information and its index, so they are treated as a tab opened as a child of some another tab with specific index - TST respects them. The option "any other case" should affect to cases only when there is no hint to construct tree structure for a newly opened tab, and it won't affect to this case by design, sorry.

I think you should use something another extension to enforce "open new tab next to the current tab" behavior (sorry I don't know such an extension actually exists or not). It is clearly out of purpose of this TST project.

there is one and i use it myself, works well enough although not perfect all of the time, but i also can't tell which addon in the chain is responsible for the occasional faulty interaction: https://addons.mozilla.org/en-US/firefox/addon/open-tabs-next-to-current/

@piroor Thank you for the explanation. I apologize if I'm not clear about this. I would like the new option to not affect the restore position of closed tabs, as you have described. TST should respect the tree structure information, and put the restored tab back to the same place. It sounds like that's what you intend, so I think we agree! But I'm experiencing that it does affect restored tabs. I think it's a bug.

The option "any other case" should affect to cases only when there is no hint to construct tree structure for a newly opened tab, and it won't affect to this case by design, sorry.

Yes, that's exactly what I would like (and that's how browser.tabs.insertAfterCurrent works - it doesn't affect restored tabs). But in some cases, I find that the "Tabs from any other trigger" option does affect where closed tabs are restored. When a closed tab is a root tab, i.e., has no parent, it will be restored to a different place depending on the setting of "Tabs from any other trigger".

Steps to reproduce:

  1. Create a new profile and install only TST 3.7.1 with default settings.
  2. Create five new tabs. Make the second one a child of the first tab.
  3. Close the fourth tab, and select the first tab.
  4. Press shift-cmd-T to restore the closed tab.
  5. Note that it restores to the place it was before, the fourth tab, as expected. It doesn't matter which tab is selected when it's restored, it always restores to the fourth position as expected.
  6. In TST expert options, set "Tabs from any other trigger" to "a child of the current tab" or "the next sibling" (behaviour is the same).
  7. Again close the fourth tab, select the first or second tab, and press shift-cmd-T to restore.

    • Expected behaviour: the tab restores to the place it was before, the fourth tab.

    • Actual behaviour: the tab is restored as the third tab, with no parent.

  8. Move the restored tab back to the fourth position.
  9. In TST expert options, set "Tabs from any other trigger" to "a sibling of the current tab"
  10. Close the fourth tab, select the first, second, or third tab, and press shift-cmd-T to restore.

    • Expected behaviour: the tab restores to the place it was before, the fourth tab.

    • Actual behaviour: the tab is restored in different places, depending which tab is selected when it's restored.

In addition to affecting the restore of closed root tabs (without parents), the "Tabs from any other trigger" option also affects the use of Tab Session Manager. When a session is restored, root tabs follow the option, so for example if you set it to "a child of the current tab", then all root tabs are restored as children of the first tab; with "next sibling", the root tabs are restored in reverse order. If necessary, I can open an issue with TSM, if there's a solution for this.

Again, to be clear, the option would be perfect if it worked the way you described above, and did not affect restored tabs. I think it's not possible for another addon to do this, because it's not aware of the tree of tabs, so it can't allow e.g. "next sibling". I hope it could be fixed...

PS, @mimecry thanks, but that addon affects new blank tabs, and I'm happy with the way that works in TST already. What I want is exactly what "Tabs from any other trigger" option should do, as Piro has described it. However, if you have problems with "Open tabs next to current" addon, you could maybe try "Always Right"? It seems to be more consistent.

@ElhemEnohpi Thanks, I've fixed the inconsistency, with the commit 39190238e. TST applies old tree structure for a restored tab after it was controlled as a new tab from unknown trigger, and the combination resulted unexpected position.

Restoring with "undo closed tab" seems to be working now, thanks!

I'm continuing with testing. I found that it also affects new blank tabs that are opened as an independent tab by TST. For example, if you set click or middle-click etc. on new tab button to "independent tab", or if you choose "independent tab" from the selector button, it will open according to the "Tabs from any other trigger" setting instead.

There's still the problem with Tab Session Manager, that when restoring a session, tabs without parents are affected by the "Tabs from any other trigger" setting. Do you think this can be solved in TST, for example by not applying the setting if index is specified, or better solved in TSM, for example by using move-to-end after making a tab that has no openerTabID? Or some other solution?

For example, if you set click or middle-click etc. on new tab button to "independent tab", or if you choose "independent tab" from the selector button, it will open according to the "Tabs from any other trigger" setting instead.

Thanks, it is a bug and should be fixed with the commit ca2da89.

There's still the problem with Tab Session Manager, that when restoring a session, tabs without parents are affected by the "Tabs from any other trigger" setting.

It is one of major, expected (and of course not desired) side effects of the new option, and that is the reason why I didn't add the option.

for example by not applying the setting if index is specified

Hmm, it looks effective only for tabs opened in middle of existing tabs. Even if a new tab is opened with the last index explicitly, TST cannot know that - such a tab and opened with no index hint both have same index.

I think it is a bad idea that struggling around this conflict with TSM, for both TST and TSM. The root problem is poorness of WebExtensions API, and too much workarounds make things too complicated. What problems we should solve are:

  • Firefox doesn't provide any information to detect "new tab opened from external application"
  • Firefox doesn't provide any information to detect "new tab opened by another addon"

We should file bugs at bugzilla.mozilla.org - we need to propose API changes.

Thanks for fixing that bug, and for the other information.

I can see that it would be better if there was an improvement to the extensions API, instead of having to guess at how tabs were opened. For now, I'm just turning it off when I need to restore a session. Otherwise, it seems to be working well, and it's a big improvement for me, so thanks again. Fyi, I use the "PopClip" app, which offers many options like translate or search for selected text, and it's great to be able to control where the tabs are opened now.

Originally, I thought that TSM created tabs through the TST API, but I see that it's not so. I wonder if a tab-opening function in the TST API would be something to consider? That way, other addons that are aware of TST could add extra information, e.g. to request that a tab be opened in a certain way on the tree. It could also help with the problem that TSM has to use a delay after opening tabs, to wait for TST to move them, and sometimes the delay is either too long or too short. If TSM could request TST to open tabs, then sessions could be restored more quickly, without the risk of errors.

Ultimately, we need a better Firefox API to allow extensions to restore sessions using Firefox built-in methods, so that all addons' private session information (and tab history, etc.) can be restored in the same way that Firefox restore previous session on startup works. That's bug 1413525; unfortunately there hasn't been much interest from Mozilla...

Fyi, I use the "PopClip" app, which offers many options like translate or search for selected text, and it's great to be able to control where the tabs are opened now.

Hmm, it would work with TST better if it was provided as a browser addon instead of a native application... A browser addon can open a new tab with an extra information "the opener tab", and TST treats such a tab as a child of the opener tab by default, but native applications cannot do that.

Indeed, an addon Swift Selection Search looks to cover some features of the PopClip. I've installed it and configured it to open results in new tabs, then I've successfully gotten results as child tabs. How about it?

The reason why I'm negative to provide APIs like opening of tabs is: TST is just a choice for very limited number of people. TST has about 145K users for now, on the other hand there are over 200M Firefox users, thus TST is running on only 0.07% or less Firefox environment. Requesting "please use TST's custom API instead of Firefox's WebExtensions API to open tabs" to addon authors by me looks too egoistic...

Well, Piro, you don't need to be so modest! TST is in the top 25 of "recommended" extensions by number of users, and I think it's one of the most famous addons... In any case, most addons wouldn't need to use the tab-opening API, especially if there was an improved Firefox API to indicate a tab opened by an addon. But for some that specifically have support for TST, like TSM, it could provide some advantages. I think many people use TST and TSM together, and for them especially speeding up session restore would be appreciated. (That it might also help with my problem with "tabs from any other trigger" is more of a side-effect...) I can't say whether sienori would have time for it. If not, I might try to hack it myself, though I don't know javascript very well.

Thanks for your suggestion of another addon to use instead of PopClip. In the past I've used some such addons, but I like that I have a consistent interface that works with all other applications, like e-mail, notes, etc. It can do many other kinds of text manipulation too, not just searching. Anyway, I actually really like the way the "tabs from any other trigger" is working, not only for PopClip. I think for me there's only this one problem with TSM now.

PS, I've been using TST for many years, but you haven't heard much from me lately because I was using legacy TST with Waterfox the past few years, so that I could use the original Session Manager (also I changed my user name). But Waterfox "classic" became too unstable, so I'm back with Firefox. It's very nice to have all the improvements in TST since then!

If TST provides a new API to open new tabs, there can be another problem about security.

When an addon tries to create a new tab, the tabs.create() method returns a tab object without its URL and some sensitive information, even if it was requested from the addon itself. Thus such an addon need to list tabs in its permissions in the manifest file.

TST's API should simulate the behavior. However TST cannot know the requestor addon has tabs permission or not, so TST still needs to return tab objects without sensitive information. To avoid this restriction TST provides its own permission system for helper addons. This means that addons like TSM need to think not only about how to create new tabs but about custom permissions for TST also. I'm afraid that it will increase maintenance cost of addons which decided to support TST.

Anyway, if they other addon authors accept to use such a bothersome method, it can be a solution. I've added a new API create, it is compatible to tabs.create() so it may be called like as:

const params = { url: 'https://example.com/', windowId: 1 };
let tab;
if (useTST)
  tab = await browser.runtime.sendMessage(
    '[email protected]',
    { type:'create', params }
  ).catch(error => { console.error(error); return null; })
else
  tab = await browser.tabs.create(params);

The document: https://github.com/piroor/treestyletab/wiki/API-for-other-addons#open-new-tab-bypassing-tsts-tab-control-behavior

@piroor or @ElhemEnohpi is there more to discuss or do here ... or can we close this item?

I think no more what I can do on TST side, thus I close this.

Was this page helpful?
0 / 5 - 0 ratings