From 967bafa1fc731bd2b78497ba6e821126c816a232 Mon Sep 17 00:00:00 2001 From: Roy-Orbison Date: Tue, 24 Aug 2021 11:55:41 +0930 Subject: [PATCH] Rework entire extension - Add a feature to remember last explicit container and open new tabs in that when the current tab is in the default "no" container. - Change default shortcut to use two modifier keys to make it more reliable. Signed-off-by: Roy-Orbison --- CONTRIBUTING.md | 35 --------------- LICENSE.txt | 2 +- README.md | 7 ++- background.js | 116 +++++++++++++++++++++++++++++++++++++++++------- icon.svg | 11 +++++ img/icon.svg | 13 ------ manifest.json | 63 +++++++++++++++++--------- options.html | 40 +++++++++++++++++ options.js | 27 +++++++++++ 9 files changed, 228 insertions(+), 86 deletions(-) delete mode 100644 CONTRIBUTING.md create mode 100644 icon.svg delete mode 100644 img/icon.svg create mode 100644 options.html create mode 100644 options.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 0681439..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,35 +0,0 @@ -# Contributing - -Everyone is welcome to contribute to containers. Reach out to team members if you have questions: - -- IRC: #containers on irc.mozilla.org -- Email: containers@mozilla.com - -## Filing bugs - -If you find a bug with containers, please file a issue. - -Check first if the bug might already exist: https://github.com/mozilla/testpilot-containers/issues - -[Open an issue](https://github.com/mozilla/testpilot-containers/issues/new) - -1. Visit about:support -2. Click "Copy raw data to clipboard" and paste into the bug. Alternatively copy the following sections into the issue: - - Application Basics - - Nightly Features (if you are in nightly) - - Extensions - - Experimental Features -3. Include clear steps to reproduce the issue you have experienced. -4. Include screenshots if possible. - -## Sending Pull Requests - -Patches should be submitted as pull requests. When submitting patches as PRs: - -- You agree to license your code under the project's open source license (MPL 2.0). -- Base your branch off the current master (see below for an example workflow). -- Add both your code and new tests if relevant. -- Run npm test to make sure all tests still pass. -- Please do not include merge commits in pull requests; include only commits with the new relevant code. - -See the main [README](./README.md) for information on prerequisites, installing, running and testing. diff --git a/LICENSE.txt b/LICENSE.txt index 14e2f77..a612ad9 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -35,7 +35,7 @@ Mozilla Public License Version 2.0 means any form of the work other than Source Code Form. 1.7. "Larger Work" - means a work that combines Covered Software with other material, in + means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" diff --git a/README.md b/README.md index b448338..6452666 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ -# New container tab +# Retainer -Creates a new container tab based upon the current one when you use Alt+C. +Provides a keyboard shortcut (Shift + Alt + C by default) to create a new tab that retains the current/last-used container. + +You can edit the default shortcut under _Add-ons and Themes > Extensions > :gear: > Manage Extension Shortcuts > Retainer_. +New tabs can be restricted to the last-used container in the extension's preferences panel under *Add-ons and Themes > Extensions > Retainer > ⋯ > Preferences*. diff --git a/background.js b/background.js index 19a58e9..8355107 100644 --- a/background.js +++ b/background.js @@ -1,17 +1,103 @@ -browser.commands.onCommand.addListener(function(command) { - if (command == "new-container-tab") { - createContainerTab(); - } -}); +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/ + * + * © 2017 Jonathan Kingston + * © 2021 Roy Orbison + * */ -async function createContainerTab() { - const tabs = await browser.tabs.query({ - currentWindow: true, - active: true - }); - const tab = tabs[0]; - browser.tabs.create({ - index: tab.index + 1, - cookieStoreId: tab.cookieStoreId - }); +class WindowContainers { + set(tab) { + if ( + tab.cookieStoreId + && tab.windowId + && tab.cookieStoreId !== containerNone + ) { + this[tab.windowId] = tab.cookieStoreId; + } + } } + +const containers = new WindowContainers; +const containerNone = 'firefox-default'; + + +browser.windows.onRemoved.addListener(windowId => delete containers[windowId]); + +(async function() { + try { + const actives = await browser.tabs.query({ + active: true + }); + if (actives?.length) { + actives.forEach(async function(tab) { + if (tab.windowId && tab.cookieStoreId == containerNone) { + const others = await browser.tabs.query({ + windowId: tab.windowId + }); + if (others?.length) { + let counts = {}, + stable = []; + others.forEach(tabOther => { + if (tabOther.cookieStoreId && tabOther.cookieStoreId != containerNone) { + stable[tabOther.index] = tabOther.cookieStoreId + if (counts[tabOther.cookieStoreId]) { + counts[tabOther.cookieStoreId].count++; + } + else { + counts[tabOther.cookieStoreId] = { + count: 1, + oneOf: tabOther + }; + } + } + }); + if (stable.length) { + stable = stable.reduce((containerLast, containerCurrent) => + containerLast + && ( + !containerCurrent + || counts[containerLast].count > counts[containerCurrent].count + ) ? + containerLast : + containerCurrent); + tab = counts[stable].oneOf; + } + } + } + containers.set(tab); + }); + } + } + catch (error) { + } +})(); + +browser.tabs.onActivated.addListener(async function(activeInfo) { + try { + const tab = await browser.tabs.get(activeInfo.tabId); + containers.set(tab); + } + catch (error) { + } +}); + +browser.commands.onCommand.addListener(async function(command) { + if (command === 'retainer-tab') { + try { + const tabs = await browser.tabs.query({ + currentWindow: true, + active: true + }); + if (tabs?.length) { + const exclKey = 'excludeDefault', + res = await browser.storage.sync.get(exclKey); + browser.tabs.create({ + cookieStoreId: res && res[exclKey] && containers[tabs[0].windowId] || tabs[0].cookieStoreId + }); + } + } + catch (error) { + } + } +}); diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..f588018 --- /dev/null +++ b/icon.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/img/icon.svg b/img/icon.svg deleted file mode 100644 index 2c18378..0000000 --- a/img/icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - -firefox - - - - diff --git a/manifest.json b/manifest.json index 6e42707..253b36d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,22 +1,45 @@ { - "name": "New container tab", - "version": "0.2.0", - "description": "Press Alt+C to create a new container tab.", - "author": "Jonathan Kingston", - "icons": { - "128": "img/icon.svg" - }, - "background": { - "scripts": ["background.js"] - }, - "permissions": [ - "cookies" - ], - "commands": { - "new-container-tab": { - "suggested_key": { "default": "Alt+C" }, - "description": "Create a new container tab" - } - }, - "manifest_version": 2 + "licence": "This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. If a copy of the MPL was not distributed with this file, you can obtain one at https://mozilla.org/MPL/2.0/", + "copyright": "© 2017 Jonathan Kingston, © 2021 Roy Orbison", + "manifest_version": 2, + "name": "Retainer", + "author": "Roy Orbison", + "version": "0.1.0", + "description": "Provides a keyboard shortcut (Shift + Alt + C by default) to create a new tab that retains current/last-used container.", + "icons": { + "16": "icon.svg", + "32": "icon.svg", + "48": "icon.svg", + "96": "icon.svg", + "128": "icon.svg", + "512": "icon.svg" + }, + "homepage_url": "https://github.com/Roy-Orbison/Retainer", + "browser_specific_settings": { + "gecko": { + "id": "retainer@roy-orbison.test", + "strict_min_version": "58.0a1" + } + }, + "background": { + "scripts": [ + "background.js" + ] + }, + "permissions": [ + "tabs", + "storage", + "cookies" + ], + "commands": { + "retainer-tab": { + "suggested_key": { + "default": "Shift+Alt+C" + }, + "description": "New retained tab" + } + }, + "options_ui": { + "page": "options.html" + } } diff --git a/options.html b/options.html new file mode 100644 index 0000000..23fa0c1 --- /dev/null +++ b/options.html @@ -0,0 +1,40 @@ + + + + + + Retainer options page + + + +
+ +
+ + + diff --git a/options.js b/options.js new file mode 100644 index 0000000..26bcf2f --- /dev/null +++ b/options.js @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/ + * + * © 2021 Roy Orbison + * */ + +const excludeCheckbox = document.querySelector('#exclude-default'), + exclKey = 'excludeDefault', + store = browser.storage.sync; +excludeCheckbox.indeterminate = true; + +store.get(exclKey).then(res => { + excludeCheckbox.disabled = false; + excludeCheckbox.indeterminate = false; + excludeCheckbox.checked = !!(res && res[exclKey]); + + excludeCheckbox.addEventListener('change', function() { + excludeCheckbox.indeterminate = true; + const upd = { + [exclKey]: excludeCheckbox.checked + }; + store.set(upd) + .finally(() => excludeCheckbox.indeterminate = false) + .catch(() => excludeCheckbox.checked = !upd[exclKey]); + }); +});