Safari Web Extension tab ids are 0 during webNavigation callbacks until onCompleted event

Safari Version 14.0.1 (16610.2.11.51.8)

I am porting a Chrome/Firefox/Edge extension to Safari Web Extension. Mostly, the process was painless, I am, however, seeing quite different behavior in the tab ids generated by Safari compared to Chrome, Firefox, and Edge. My extension has callbacks for each of these browser.webNavigation events:

Code Block
browser.webNavigation.onBeforeNavigate
browser.webNavigation.onCommitted
browser.webNavigation.onDOMContentLoaded

In each of these I rely on the tab id for various future tab targeting operations. When opening a new tab, the details object passed to each of these callbacks has a non-zero tabId on Chrome, Firefox, and Edge. However, in Safari, the tabId is always zero. To debug, I added one more callback:

Code Block
browser.webNavigation.onCompleted

At this point Safari finally has a non-zero tabId in the details param. Needless to say this is causing some consternation with achieving the same outcomes as tab tracking on Chrome, Firefox, and Edge. It's like Safari is treating new tabs as "non tabs" until navigation completes. You can even see it when trying to get the tab by tabId=0:

Code Block
browser.tabs.get(tabId) // tabId=0 here
.then(tab => {
// tab is undefined
});


Seems like this might be a bug. I can't imagine why the behavior is so different from other browsers. Any ideas on how to work around?
I think I found a workaround myself...still testing though. It appears if you get the currently active tab when then tab id is 0, you can get the REAL tab id. Example:

Code Block
private getRealTabId(tabId: number): Promise<number> {
return browser.tabs.get(tabId) // tabId=0 here
.then((tab: Tab) => {
if (!tab) {
console.debug(`Could not find tabId=${tabId}. Looking for active tab.`);
return browser.tabs.query({active: true, currentWindow: true})
.then((tabs: Tab[]) => {
if (tabs.length) {
const tab = tabs[0];
console.debug(`Found active tab for tabId=${tabId} with tabId=${tab.id}`);
return tab.id; // this tab id is non-zero! yay!
}
throw new Error("Tab not found");
})
}
return tabId;
});
}


This would not be a perfect solution, though, since a user could be quickly switching tabs and thus resulting in a new active tab, but it may be "good enough" for now.

Can we get more info on this?

Not having access to the actual tabId limits extension potential for pre-processing before the load events.

This is still the case with Safari 15.2

testing on Safari 15.4, even browser.webNavigation.onCompleted also behaves unstably

It can get non zero tabId, but can still return zero tabId sometimes.

My test procedure

  1. open a new tab
  2. go to foo.com
  3. close the tab

Repeat 1~3 many times, it looks like the first time onCompleted callback still return 0 tabId

However I also encountered that some website always return 0 tabId no matter how many times I try

Because of the unstable results, it indeed brings quite some hassle and confusion. The root cause is also unclear, it works for some website but not for others, is it related with the website itself? or my safari settings? or even my machine's settings.

Hopefully it can be fixed or documented.

Safari Web Extension tab ids are 0 during webNavigation callbacks until onCompleted event
 
 
Q