diff --git a/src/_locales b/src/_locales index 30aab7b..6f74e69 160000 --- a/src/_locales +++ b/src/_locales @@ -1 +1 @@ -Subproject commit 30aab7b6d876f02d22186bb534e84eefd8e1a2da +Subproject commit 6f74e692138082d0f6de4c40e6c2d1f5fe717005 diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index fb90ba6..34c7696 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* global MAC_CONSTANTS */ + const DEFAULT_TAB = "about:newtab"; const backgroundLogic = { @@ -11,22 +13,33 @@ const backgroundLogic = { "about:home", "about:blank" ]), - NUMBER_OF_KEYBOARD_SHORTCUTS: 10, + NUMBER_OF_KEYBOARD_SHORTCUTS: MAC_CONSTANTS.NUMBER_OF_KEYBOARD_SHORTCUTS, unhideQueue: [], - init() { - browser.commands.onCommand.addListener(function (command) { + init() { + browser.commands.onCommand.addListener(async function (command) { if (command === "sort_tabs") { backgroundLogic.sortTabs(); return; } for (let i=0; i < backgroundLogic.NUMBER_OF_KEYBOARD_SHORTCUTS; i++) { - const key = "open_container_" + i; - const cookieStoreId = identityState.keyboardShortcut[key]; + const key = MAC_CONSTANTS.OPEN_CONTAINER_PREFIX + i; + const reopenKey = MAC_CONSTANTS.REOPEN_IN_CONTAINER_PREFIX + i; if (command === key) { - if (cookieStoreId === "none") return; - browser.tabs.create({cookieStoreId}); + const cookieStoreId = identityState.keyboardShortcut[key]; + if (cookieStoreId && cookieStoreId !== "none") { + browser.tabs.create({cookieStoreId}); + } + return; + } + + if (command === reopenKey) { + const cookieStoreId = identityState.keyboardShortcut[reopenKey]; + if (cookieStoreId && cookieStoreId !== "none") { + backgroundLogic.reopenInContainer(cookieStoreId); + } + return; } } }); @@ -69,6 +82,23 @@ const backgroundLogic = { } }, + async reopenInContainer(cookieStoreId) { + const currentTab = await browser.tabs.query({ active: true, currentWindow: true }); + + if (currentTab.length > 0) { + const tab = currentTab[0]; + + browser.tabs.create({ + url: tab.url, + cookieStoreId, + index: tab.index + 1, + active: tab.active + }); + + browser.tabs.remove(tab.id); + } + }, + /** * We left an achievement entry in storage during a user research study in * version 8.3.1. This method removes that entry to prevent broken logic in @@ -84,11 +114,15 @@ const backgroundLogic = { }, updateTranslationInManifest() { - for (let index = 0; index < 10; index++) { - const ajustedIndex = index + 1; // We want to start from 1 instead of 0 in the UI. + for (let index = 0; index < MAC_CONSTANTS.NUMBER_OF_KEYBOARD_SHORTCUTS; index++) { + const adjustedIndex = index + 1; // We want to start from 1 instead of 0 in the UI. browser.commands.update({ - name: `open_container_${index}`, - description: browser.i18n.getMessage("containerShortcut", `${ajustedIndex}`) + name: `${MAC_CONSTANTS.OPEN_CONTAINER_PREFIX}${index}`, + description: browser.i18n.getMessage("containerShortcut", `${adjustedIndex}`) + }); + browser.commands.update({ + name: `${MAC_CONSTANTS.REOPEN_IN_CONTAINER_PREFIX}${index}`, + description: browser.i18n.getMessage("reopenInContainerShortcut", `${adjustedIndex}`) }); } }, diff --git a/src/js/background/constants.js b/src/js/background/constants.js new file mode 100644 index 0000000..f7f547c --- /dev/null +++ b/src/js/background/constants.js @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Shared constants for background scripts +window.MAC_CONSTANTS = { + OPEN_CONTAINER_PREFIX: "open_container_", + REOPEN_IN_CONTAINER_PREFIX: "reopen_in_container_", + NUMBER_OF_KEYBOARD_SHORTCUTS: 10, +}; diff --git a/src/js/background/identityState.js b/src/js/background/identityState.js index 9114240..8d3d52f 100644 --- a/src/js/background/identityState.js +++ b/src/js/background/identityState.js @@ -1,3 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* global MAC_CONSTANTS */ window.identityState = { keyboardShortcut: {}, storageArea: { @@ -50,18 +55,22 @@ window.identityState = { async loadKeyboardShortcuts () { const identities = await browser.contextualIdentities.query({}); - for (let i=0; i < backgroundLogic.NUMBER_OF_KEYBOARD_SHORTCUTS; i++) { - const key = "open_container_" + i; - const storageObject = await this.area.get(key); - if (storageObject[key]){ - identityState.keyboardShortcut[key] = storageObject[key]; - continue; + for (let i=0; i < MAC_CONSTANTS.NUMBER_OF_KEYBOARD_SHORTCUTS; i++) { + const openKey = MAC_CONSTANTS.OPEN_CONTAINER_PREFIX + i; + const reopenKey = MAC_CONSTANTS.REOPEN_IN_CONTAINER_PREFIX + i; + + for (const key of [openKey, reopenKey]) { + const storageObject = await this.area.get(key); + + if (storageObject[key]){ + identityState.keyboardShortcut[key] = storageObject[key]; + } else if (identities[i]) { + identityState.keyboardShortcut[key] = identities[i].cookieStoreId; + } else { + identityState.keyboardShortcut[key] = "none"; + } } - if (identities[i]) { - identityState.keyboardShortcut[key] = identities[i].cookieStoreId; - continue; - } - identityState.keyboardShortcut[key] = "none"; + } return identityState.keyboardShortcut; }, diff --git a/src/js/background/index.html b/src/js/background/index.html index 818dbb4..6922190 100644 --- a/src/js/background/index.html +++ b/src/js/background/index.html @@ -15,6 +15,7 @@ --> + diff --git a/src/manifest.json b/src/manifest.json index 94de8ed..6215b1c 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -109,6 +109,36 @@ "default": "Ctrl+Shift+0" }, "description": "__MSG_containerShortcut__" + }, + "reopen_in_container_0": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_1": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_2": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_3": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_4": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_5": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_6": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_7": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_8": { + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_9": { + "description": "__MSG_reopenInContainerShortcut__" } }, "browser_action": { diff --git a/test/features/reopen-shortcuts.test.js b/test/features/reopen-shortcuts.test.js new file mode 100644 index 0000000..c9d0b9f --- /dev/null +++ b/test/features/reopen-shortcuts.test.js @@ -0,0 +1,44 @@ +const {initializeWithTab} = require("../common"); + +describe("Reopen Shortcuts Feature", function () { + beforeEach(async function () { + // Initialize with a tab in the default container + this.webExt = await initializeWithTab({ + cookieStoreId: "firefox-default", + url: "https://example.com" + }); + }); + + afterEach(function () { + this.webExt.destroy(); + }); + + describe("when using keyboard shortcut to reopen in container", function () { + beforeEach(async function () { + // Simulate the keyboard shortcut command + await this.webExt.background.browser.commands.onCommand.addListener.firstCall.args[0]("reopen_in_container_0"); + }); + + it("should open the page in the assigned container and close the original tab", async function () { + this.webExt.background.browser.tabs.create.should.have.been.calledWithMatch({ + url: "https://example.com", + cookieStoreId: "firefox-container-1", + index: 1, + active: true + }); + + this.webExt.background.browser.tabs.remove.should.have.been.called; + }); + }); + + describe("when container is set to 'none'", function () { + beforeEach(async function () { + await this.webExt.background.browser.commands.onCommand.addListener.firstCall.args[0]("reopen_in_container_9"); + }); + + it("should not reopen the tab", function () { + this.webExt.background.browser.tabs.create.should.not.have.been.called; + this.webExt.background.browser.tabs.remove.should.not.have.been.called; + }); + }); +});