gh-14183: Dont open space routing tabs in background (gh-14360)

This commit is contained in:
mr. m
2026-06-24 11:25:39 +02:00
committed by GitHub
parent 54692261f8
commit 4e9c958f8d
3 changed files with 68 additions and 21 deletions

View File

@@ -35,13 +35,6 @@ export class ZenSpaceRoutingNavigation extends ZenUIComponent {
return;
}
// The tab we spawn for a route must be allowed to load once without being
// redirected again, regardless of when its workspace attribute lands.
if (aBrowser._zenSkipNavRouteOnce) {
aBrowser._zenSkipNavRouteOnce = false;
return;
}
let uri;
try {
uri = aRequest.QueryInterface(Ci.nsIChannel).URI;
@@ -80,16 +73,49 @@ export class ZenSpaceRoutingNavigation extends ZenUIComponent {
}
const currentWorkspaceId = tab.getAttribute("zen-workspace-id");
if (
!win.gZenSpaceRoutingManager.shouldRedirectNavigation(
const targetWorkspaceId =
win.gZenSpaceRoutingManager.getRedirectTargetWorkspaceId(
uri.spec,
currentWorkspaceId,
win
)
) {
);
if (!targetWorkspaceId) {
return;
}
// A brand-new tab whose very first real navigation this is (a
// target="_blank" link, window.open(), or a freshly opened tab) is still
// showing its initial about:blank document. There is nothing to preserve,
// so rather than cancelling the load and spawning a duplicate tab - which
// would leave this one behind empty - just move this very tab into the
// destination space and let the in-flight load finish in place.
const isInitialDocument =
aBrowser.browsingContext?.currentWindowGlobal?.isInitialDocument ?? false;
if (isInitialDocument) {
const wasSelected = tab.selected;
// Defer so we don't mutate the tab strip from inside a progress notification.
win.setTimeout(() => {
if (!tab.isConnected) {
return;
}
gBrowser.selectedTab = tab.owner;
win.gZenWorkspaces.moveTabToWorkspace(tab, targetWorkspaceId);
if (wasSelected) {
const targetWorkspace =
win.gZenWorkspaces.getWorkspaceFromId(targetWorkspaceId);
if (targetWorkspace) {
win.gZenWorkspaces.lastSelectedWorkspaceTabs[targetWorkspaceId] =
tab;
win.gZenWorkspaces.changeWorkspace(targetWorkspace);
}
}
}, 0);
return;
}
// An already-loaded page is navigating in place. Preserve it in its current
// tab and re-open the destination in a new routed tab instead.
//
// Under Fission the parent-side aRequest is a RemoteWebProgress stand-in
// whose cancel()/loadInfo throw NS_ERROR_NOT_IMPLEMENTED (the real channel
// lives in the content process). Stop the in-place load through the browser,
@@ -111,13 +137,14 @@ export class ZenSpaceRoutingNavigation extends ZenUIComponent {
// Defer so we don't mutate the tab strip from inside a progress notification.
win.setTimeout(() => {
const newTab = gBrowser.addTab(urlToOpen, {
gBrowser.addTab(urlToOpen, {
triggeringPrincipal: principal,
ownerTab: tab.isConnected ? tab : null,
// The user was actively navigating this tab, so follow the navigation
// into the routed tab instead of opening it in the background (addTab
// defaults inBackground to true).
inBackground: false,
});
if (newTab?.linkedBrowser) {
newTab.linkedBrowser._zenSkipNavRouteOnce = true;
}
}, 0);
}
}

View File

@@ -104,7 +104,7 @@ class nsZenSpaceRoutingManager {
break;
default: {
const targetWorkspace =
win?.gZenWorkspaces?.getWorkspaceFromId(targetRoute);
win.gZenWorkspaces.getWorkspaceFromId(targetRoute);
if (targetWorkspace) {
userContextId = targetWorkspace.containerTabId;
@@ -159,8 +159,26 @@ class nsZenSpaceRoutingManager {
* @returns {boolean} True when the navigation should open in a new routed tab
*/
shouldRedirectNavigation(uriString, currentWorkspaceId, win) {
return !!this.getRedirectTargetWorkspaceId(
uriString,
currentWorkspaceId,
win
);
}
/**
* Resolves the destination space for an in-place top-level navigation, or
* null when the navigation should be left alone (no rule, the destination is
* "most-recent-space", the tab already lives there, or the space is gone).
*
* @param {string} uriString - The destination URI
* @param {string|null} currentWorkspaceId - The zen-workspace-id of the navigating tab
* @param {Window} win - The owning browser window
* @returns {string|null} The target workspace id, or null to leave the navigation in place
*/
getRedirectTargetWorkspaceId(uriString, currentWorkspaceId, win) {
if (!win?.gZenWorkspaces?.workspaceEnabled) {
return false;
return null;
}
const targetRoute = this.routeUri(uriString, { fromExternal: false });
@@ -170,11 +188,13 @@ class nsZenSpaceRoutingManager {
targetRoute === "most-recent-space" ||
targetRoute === currentWorkspaceId
) {
return false;
return null;
}
// Only redirect when the destination space actually exists.
return !!win.gZenWorkspaces.getWorkspaceFromId(targetRoute);
return win.gZenWorkspaces.getWorkspaceFromId(targetRoute)
? targetRoute
: null;
}
/**

View File

@@ -2298,12 +2298,12 @@ class nsZenWorkspaces {
}
onBeforeTabSelect(aTab) {
if (this.#inChangingWorkspace) {
if (this.#inChangingWorkspace || !aTab) {
// Just in case, Let's not do these checks while we are
// in the middle of changing workspace,
return false;
}
const tabSpace = aTab?.getAttribute("zen-workspace-id");
const tabSpace = aTab.getAttribute("zen-workspace-id");
if (
tabSpace &&
tabSpace !== this.activeWorkspace &&