Open new tabs in same container as previous tab.
This commit adds functionality that will try to open new tabs in the same container as the previously active tab in that window, if the new tab doesn't already have a container, and the previously active tab did. Some undocumented / implicity functionality in the webextension API is used: * `onCreated` is called for a new tab before `onActivated` for that tab is called * `onUpdated` will be called for all new tabs, also `about:newtab` and the like (sets the favicon) * The first `onUpdated` for a new tab, that is not an `about:`-tab, will set the URL It is a little bit wonky, as the original new tab is created and displayed (although not loaded) before it can be closed a new tab can be created. However, it is the best workaround I can find to add this functionality until Bugzilla 1406371 is solved. This would fix #462, #448 and #406 (I think) Also relates to #943 and #544
This commit is contained in:
parent
abd2b73fca
commit
b471cc2fdf
1 changed files with 87 additions and 0 deletions
|
@ -177,6 +177,93 @@ const assignManager = {
|
|||
browser.webRequest.onBeforeRequest.addListener((options) => {
|
||||
return this.onBeforeRequest(options);
|
||||
},{urls: ["<all_urls>"], types: ["main_frame"]}, ["blocking"]);
|
||||
|
||||
// We need to keep track over the last activated tab, in order to open new
|
||||
// tabs in the correct container. See the comments in _onTabCreated for
|
||||
// more details
|
||||
this.lastActivatedTab = new Map();
|
||||
browser.tabs.onActivated.addListener((info) => {
|
||||
this._onTabActivated(info);
|
||||
});
|
||||
// We need to query for the currently active tabs, to support
|
||||
// hot-reloading of the extensions, and possibly also for functioning on
|
||||
// browser startup
|
||||
browser.tabs.query({active: true}).then(active => {
|
||||
active.forEach(tab => {
|
||||
this.lastActivatedTab.set(tab.windowId, tab.id);
|
||||
});
|
||||
}).catch();
|
||||
|
||||
// Add listener that reopens new tabs without container in the same
|
||||
// container as the last tab.
|
||||
browser.tabs.onCreated.addListener((tab) => {
|
||||
this._onTabCreated(tab);
|
||||
});
|
||||
},
|
||||
|
||||
_onTabActivated(info) {
|
||||
this.lastActivatedTab.set(info.windowId, info.tabId);
|
||||
},
|
||||
|
||||
async _onTabCreated(tab) {
|
||||
// Here we rely on the fact that the new tab is created before it can be
|
||||
// activated, so that the "currently active" tab before this set of event
|
||||
// executions is really the previous tab
|
||||
const previousTabId = this.lastActivatedTab.get(tab.windowId);
|
||||
if (!previousTabId) {
|
||||
return;
|
||||
}
|
||||
|
||||
browser.contextualIdentities.get(tab.cookieStoreId).catch(() => {
|
||||
// We now know that the new tab doesn't have an identity
|
||||
return browser.tabs.get(previousTabId);
|
||||
}).then(previousTab => {
|
||||
if (tab.cookieStoreId === previousTab.cookieStoreId) {
|
||||
return;
|
||||
}
|
||||
// We now know that the previous tab did have an identity (as it is
|
||||
// different from the one the new tab has, which is none) therefore, we
|
||||
// add a listener that will reopen the tab once we know the URL.
|
||||
|
||||
// Here we rely on the fact that about:newtab and the like will get
|
||||
// an update event for setting the favicon, and that other sites will
|
||||
// get their URL in the first update event
|
||||
const updateHandler = (tabId, change, newTab) => {
|
||||
if (tabId !== tab.id) {
|
||||
return;
|
||||
} else {
|
||||
browser.tabs.onUpdated.removeListener(updateHandler);
|
||||
}
|
||||
|
||||
this.reopenIn(newTab, previousTab.cookieStoreId);
|
||||
};
|
||||
browser.tabs.onUpdated.addListener(updateHandler);
|
||||
}).catch();
|
||||
},
|
||||
|
||||
async reopenIn(tab, cookieStoreId) {
|
||||
const createTabObject = (withUrl) => {
|
||||
const obj = {
|
||||
active: tab.active,
|
||||
cookieStoreId: cookieStoreId,
|
||||
index: tab.index,
|
||||
openerTabId: tab.openerTabId,
|
||||
pinned: tab.pinned,
|
||||
windowId: tab.windowId
|
||||
};
|
||||
if (withUrl) {
|
||||
obj.url = tab.url;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
browser.tabs.create(createTabObject(true)).catch(() => {
|
||||
// We are probably going to the new tab page, which is protected, so
|
||||
// instead, we just open a plain new tab, without an URL
|
||||
return browser.tabs.create(createTabObject(false));
|
||||
}).then(() => {
|
||||
browser.tabs.remove(tab.id);
|
||||
}).catch();
|
||||
},
|
||||
|
||||
async _onClickedHandler(info, tab) {
|
||||
|
|
Loading…
Add table
Reference in a new issue