diff --git a/src/css/popup.css b/src/css/popup.css
index d5f3295..eeeaf74 100644
--- a/src/css/popup.css
+++ b/src/css/popup.css
@@ -925,6 +925,15 @@ span ~ .panel-header-text {
padding-block-end: 6px;
}
+/* https://github.com/mozilla/multi-account-containers/issues/847 */
+.container-lockorunlock.container-locked * {
+ filter: invert(0.5) sepia(1) saturate(127) hue-rotate(360deg);
+}
+
+.container-lockorunlock.container-unlocked * {
+ filter: invert(0.5);
+}
+
/* Achievement panel elements */
.share-ctas {
padding-block-end: 0.5em;
diff --git a/src/img/container-lock.svg b/src/img/container-lock.svg
new file mode 100644
index 0000000..b54c206
--- /dev/null
+++ b/src/img/container-lock.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/src/img/container-unlock.svg b/src/img/container-unlock.svg
new file mode 100644
index 0000000..58fc6b0
--- /dev/null
+++ b/src/img/container-unlock.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js
index b48db75..a8f7940 100644
--- a/src/js/background/assignManager.js
+++ b/src/js/background/assignManager.js
@@ -141,8 +141,21 @@ const assignManager = {
return {};
}
const userContextId = this.getUserContextIdFromCookieStore(tab);
- if (!siteSettings
- || userContextId === siteSettings.userContextId
+
+ // Determine if "locked out", i.e.:
+ // This request's URL is not associated with any particular contextualIdentity.
+ // But the current tab's contextualIdentity is locked. So must open request in new tab.
+ // https://github.com/mozilla/multi-account-containers/issues/847
+ let isLockedOut;
+ if (!siteSettings && "cookieStoreId" in tab) {
+ const currentContainerState = await identityState.storageArea.get(tab.cookieStoreId);
+ isLockedOut = !!currentContainerState.isLocked;
+ } else {
+ isLockedOut = false;
+ }
+
+ if ((!siteSettings && !isLockedOut)
+ || (siteSettings && userContextId === siteSettings.userContextId)
|| this.storageArea.isExempted(options.url, tab.id)) {
return {};
}
@@ -188,15 +201,22 @@ const assignManager = {
}
}
- this.reloadPageInContainer(
- options.url,
- userContextId,
- siteSettings.userContextId,
- tab.index + 1,
- tab.active,
- siteSettings.neverAsk,
- openTabId
- );
+ if (isLockedOut) {
+ // Open new tab in default context
+ // https://github.com/mozilla/multi-account-containers/issues/847
+ browser.tabs.create({url: options.url});
+ } else {
+ // Open new tab in specific context
+ this.reloadPageInContainer(
+ options.url,
+ userContextId,
+ siteSettings.userContextId,
+ tab.index + 1,
+ tab.active,
+ siteSettings.neverAsk,
+ openTabId
+ );
+ }
this.calculateContextMenu(tab);
/* Removal of existing tabs:
@@ -395,7 +415,20 @@ const assignManager = {
neverAsk: false
}, exemptedTabIds);
actionName = "added";
+
} else {
+ // Unlock container if no more assignments after this one is removed.
+ // https://github.com/mozilla/multi-account-containers/issues/847
+ const assignments = await this.storageArea.getByContainer(userContextId);
+ const assignmentKeys = Object.keys(assignments);
+ if (!(assignmentKeys.length > 1)) {
+ await backgroundLogic.lockOrUnlockContainer({
+ userContextId: userContextId,
+ isLocked: false
+ });
+ }
+
+ // Remove assignment
await this.storageArea.remove(pageUrl);
actionName = "removed";
}
diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js
index 5d71fec..a754571 100644
--- a/src/js/background/backgroundLogic.js
+++ b/src/js/background/backgroundLogic.js
@@ -123,6 +123,22 @@ const backgroundLogic = {
}
},
+ // https://github.com/mozilla/multi-account-containers/issues/847
+ async lockOrUnlockContainer(options) {
+ if (!("userContextId" in options)) {
+ return Promise.reject("lockOrUnlockContainer must be called with userContextId argument.");
+ }
+
+ const cookieStoreId = this.cookieStoreId(options.userContextId);
+ const containerState = await identityState.storageArea.get(cookieStoreId);
+ if (options.isLocked) {
+ containerState.isLocked = "locked";
+ } else {
+ delete containerState.isLocked;
+ }
+ return await identityState.storageArea.set(cookieStoreId, containerState);
+ },
+
async moveTabsToWindow(options) {
const requiredArguments = ["cookieStoreId", "windowId"];
@@ -229,7 +245,9 @@ const backgroundLogic = {
hasHiddenTabs: !!containerState.hiddenTabs.length,
hasOpenTabs: !!openTabs.length,
numberOfHiddenTabs: containerState.hiddenTabs.length,
- numberOfOpenTabs: openTabs.length
+ numberOfOpenTabs: openTabs.length,
+ // https://github.com/mozilla/multi-account-containers/issues/847
+ isLocked: !!containerState.isLocked
};
return;
});
diff --git a/src/js/background/messageHandler.js b/src/js/background/messageHandler.js
index 9578e6e..16aa583 100644
--- a/src/js/background/messageHandler.js
+++ b/src/js/background/messageHandler.js
@@ -19,6 +19,10 @@ const messageHandler = {
case "createOrUpdateContainer":
response = backgroundLogic.createOrUpdateContainer(m.message);
break;
+ case "lockOrUnlockContainer":
+ // https://github.com/mozilla/multi-account-containers/issues/847
+ response = backgroundLogic.lockOrUnlockContainer(m.message);
+ break;
case "neverAsk":
assignManager._neverAsk(m);
break;
diff --git a/src/js/popup.js b/src/js/popup.js
index 64dca45..9a14639 100644
--- a/src/js/popup.js
+++ b/src/js/popup.js
@@ -4,6 +4,9 @@
const CONTAINER_HIDE_SRC = "/img/container-hide.svg";
const CONTAINER_UNHIDE_SRC = "/img/container-unhide.svg";
+// https://github.com/mozilla/multi-account-containers/issues/847
+const CONTAINER_LOCKED_SRC = "/img/container-lock.svg";
+const CONTAINER_UNLOCKED_SRC = "/img/container-unlock.svg";
const DEFAULT_COLOR = "blue";
const DEFAULT_ICON = "circle";
@@ -252,6 +255,8 @@ const Logic = {
identity.hasHiddenTabs = stateObject.hasHiddenTabs;
identity.numberOfHiddenTabs = stateObject.numberOfHiddenTabs;
identity.numberOfOpenTabs = stateObject.numberOfOpenTabs;
+ // https://github.com/mozilla/multi-account-containers/issues/847
+ identity.isLocked = stateObject.isLocked;
}
return identity;
});
@@ -1011,7 +1016,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
}
},
- showAssignedContainers(assignments) {
+ showAssignedContainers(assignments, isLocked) {
const assignmentPanel = document.getElementById("edit-sites-assigned");
const assignmentKeys = Object.keys(assignments);
assignmentPanel.hidden = !(assignmentKeys.length > 0);
@@ -1022,6 +1027,38 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
while (tableElement.firstChild) {
tableElement.firstChild.remove();
}
+
+ /* Container locking: https://github.com/mozilla/multi-account-containers/issues/847 */
+ const lockOrUnlockIcon = isLocked ? CONTAINER_LOCKED_SRC : CONTAINER_UNLOCKED_SRC;
+ const lockOrUnlockLabel = isLocked ? "Locked" : "Unlocked";
+ const lockOrUnlockClass = isLocked ? "container-locked" : "container-unlocked";
+ const lockElement = document.createElement("div");
+ lockElement.innerHTML = escaped`
+
+