Fix cross-domain navigation staying in wrong container
Tabs now switch to the correct container when navigating to a different domain (e.g. clicking a search result on DDG). User-created containers outside ContainSite are left alone.
This commit is contained in:
@@ -10,6 +10,9 @@ let tabOrigins = {}; // tabId -> cookieStoreId (tracks which container a tab wa
|
|||||||
const CONTAINER_COLORS = ["blue", "turquoise", "green", "yellow", "orange", "red", "pink", "purple"];
|
const CONTAINER_COLORS = ["blue", "turquoise", "green", "yellow", "orange", "red", "pink", "purple"];
|
||||||
const CONTAINER_ICONS = ["fingerprint", "fence", "briefcase", "cart", "circle", "gift", "tree", "chill"];
|
const CONTAINER_ICONS = ["fingerprint", "fence", "briefcase", "cart", "circle", "gift", "tree", "chill"];
|
||||||
|
|
||||||
|
// All container IDs we've created — used for ownership checks on cross-domain navigation
|
||||||
|
const managedContainerIds = new Set();
|
||||||
|
|
||||||
// --- Domain Extraction ---
|
// --- Domain Extraction ---
|
||||||
|
|
||||||
function extractDomain(url) {
|
function extractDomain(url) {
|
||||||
@@ -128,6 +131,7 @@ async function getOrCreateContainerForDomain(baseDomain) {
|
|||||||
|
|
||||||
const cookieStoreId = container.cookieStoreId;
|
const cookieStoreId = container.cookieStoreId;
|
||||||
domainMap[baseDomain] = cookieStoreId;
|
domainMap[baseDomain] = cookieStoreId;
|
||||||
|
managedContainerIds.add(cookieStoreId);
|
||||||
await saveDomainMap();
|
await saveDomainMap();
|
||||||
|
|
||||||
const stored = await browser.storage.local.get("containerSeeds");
|
const stored = await browser.storage.local.get("containerSeeds");
|
||||||
@@ -141,33 +145,43 @@ async function getOrCreateContainerForDomain(baseDomain) {
|
|||||||
return cookieStoreId;
|
return cookieStoreId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set of tabIds we just created — skip these entirely to prevent loops
|
// tabId -> baseDomain — tabs we just created, skip only for the same domain
|
||||||
const createdByUs = {};
|
const createdByUs = {};
|
||||||
|
|
||||||
|
// Reverse lookup: find what domain a container was created for
|
||||||
|
function getContainerDomain(cookieStoreId) {
|
||||||
|
for (const [domain, cid] of Object.entries(domainMap)) {
|
||||||
|
if (cid === cookieStoreId) return domain;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle a tab that needs to be in a container for a given domain
|
// Handle a tab that needs to be in a container for a given domain
|
||||||
async function assignTabToContainer(tabId, url, baseDomain) {
|
async function assignTabToContainer(tabId, url, baseDomain) {
|
||||||
// Skip tabs we just created
|
// Skip tabs we just created — but only for the domain we created them for
|
||||||
if (createdByUs[tabId]) return;
|
if (createdByUs[tabId] === baseDomain) return;
|
||||||
if (pendingTabs[tabId]) return;
|
if (pendingTabs[tabId]) return;
|
||||||
pendingTabs[tabId] = true;
|
pendingTabs[tabId] = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const tab = await browser.tabs.get(tabId);
|
const tab = await browser.tabs.get(tabId);
|
||||||
|
const cookieStoreId = await getOrCreateContainerForDomain(baseDomain);
|
||||||
|
|
||||||
// If the tab is in ANY non-default container, leave it alone.
|
if (tab.cookieStoreId === cookieStoreId) {
|
||||||
// Either it's one of ours, or the user put it there intentionally.
|
// Already in the correct container
|
||||||
if (tab.cookieStoreId !== "firefox-default") {
|
|
||||||
delete pendingTabs[tabId];
|
delete pendingTabs[tabId];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tab is in the default (uncontained) context — assign it to the right container
|
if (tab.cookieStoreId !== "firefox-default") {
|
||||||
const cookieStoreId = await getOrCreateContainerForDomain(baseDomain);
|
// Tab is in a non-default container — only reassign if it's one we manage
|
||||||
|
if (!managedContainerIds.has(tab.cookieStoreId)) {
|
||||||
if (tab.cookieStoreId === cookieStoreId) {
|
// Not a ContainSite-managed container — leave it alone
|
||||||
delete pendingTabs[tabId];
|
delete pendingTabs[tabId];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// It's our container but wrong domain — reassign to correct container
|
||||||
|
}
|
||||||
|
|
||||||
const newTab = await browser.tabs.create({
|
const newTab = await browser.tabs.create({
|
||||||
url: url,
|
url: url,
|
||||||
@@ -175,8 +189,8 @@ async function assignTabToContainer(tabId, url, baseDomain) {
|
|||||||
index: tab.index + 1,
|
index: tab.index + 1,
|
||||||
active: tab.active
|
active: tab.active
|
||||||
});
|
});
|
||||||
// Mark the new tab so we never redirect it again
|
// Mark the new tab — only skip reassignment for this same domain
|
||||||
createdByUs[newTab.id] = true;
|
createdByUs[newTab.id] = baseDomain;
|
||||||
setTimeout(() => { delete createdByUs[newTab.id]; }, 5000);
|
setTimeout(() => { delete createdByUs[newTab.id]; }, 5000);
|
||||||
|
|
||||||
await browser.tabs.remove(tabId);
|
await browser.tabs.remove(tabId);
|
||||||
@@ -338,6 +352,7 @@ async function handleResetAll() {
|
|||||||
domainMap = {};
|
domainMap = {};
|
||||||
pendingTabs = {};
|
pendingTabs = {};
|
||||||
tabOrigins = {};
|
tabOrigins = {};
|
||||||
|
managedContainerIds.clear();
|
||||||
await browser.storage.local.clear();
|
await browser.storage.local.clear();
|
||||||
|
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
@@ -346,7 +361,6 @@ async function handleResetAll() {
|
|||||||
async function handlePruneContainers() {
|
async function handlePruneContainers() {
|
||||||
// Remove containers that have no open tabs
|
// Remove containers that have no open tabs
|
||||||
const containers = await browser.contextualIdentities.query({});
|
const containers = await browser.contextualIdentities.query({});
|
||||||
const ourContainerIds = new Set(Object.values(domainMap));
|
|
||||||
const tabs = await browser.tabs.query({});
|
const tabs = await browser.tabs.query({});
|
||||||
|
|
||||||
// Collect cookieStoreIds that have open tabs
|
// Collect cookieStoreIds that have open tabs
|
||||||
@@ -354,12 +368,12 @@ async function handlePruneContainers() {
|
|||||||
|
|
||||||
let pruned = 0;
|
let pruned = 0;
|
||||||
for (const c of containers) {
|
for (const c of containers) {
|
||||||
if (ourContainerIds.has(c.cookieStoreId) && !activeContainers.has(c.cookieStoreId)) {
|
if (managedContainerIds.has(c.cookieStoreId) && !activeContainers.has(c.cookieStoreId)) {
|
||||||
try {
|
try {
|
||||||
await browser.contextualIdentities.remove(c.cookieStoreId);
|
await browser.contextualIdentities.remove(c.cookieStoreId);
|
||||||
pruned++;
|
pruned++;
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
// domainMap cleanup happens via the onRemoved listener
|
// onRemoved listener handles domainMap + managedContainerIds cleanup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { pruned };
|
return { pruned };
|
||||||
@@ -369,6 +383,7 @@ async function handlePruneContainers() {
|
|||||||
|
|
||||||
browser.contextualIdentities.onRemoved.addListener(async ({ contextualIdentity }) => {
|
browser.contextualIdentities.onRemoved.addListener(async ({ contextualIdentity }) => {
|
||||||
const cid = contextualIdentity.cookieStoreId;
|
const cid = contextualIdentity.cookieStoreId;
|
||||||
|
managedContainerIds.delete(cid);
|
||||||
if (registeredScripts[cid]) {
|
if (registeredScripts[cid]) {
|
||||||
try { await registeredScripts[cid].unregister(); } catch(e) {}
|
try { await registeredScripts[cid].unregister(); } catch(e) {}
|
||||||
delete registeredScripts[cid];
|
delete registeredScripts[cid];
|
||||||
@@ -385,6 +400,12 @@ browser.contextualIdentities.onRemoved.addListener(async ({ contextualIdentity }
|
|||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
await loadDomainMap();
|
await loadDomainMap();
|
||||||
|
// Populate managedContainerIds from stored seeds
|
||||||
|
const stored = await browser.storage.local.get("containerSeeds");
|
||||||
|
const seeds = stored.containerSeeds || {};
|
||||||
|
for (const cid of Object.keys(seeds)) {
|
||||||
|
managedContainerIds.add(cid);
|
||||||
|
}
|
||||||
await registerAllKnownContainers();
|
await registerAllKnownContainers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user