From 8eceb0d2980114ea58e36dfe3a5808ed399ef207 Mon Sep 17 00:00:00 2001 From: Roman Rodriguez Date: Thu, 3 Oct 2019 12:39:56 -0500 Subject: [PATCH 01/13] Fix #930 - Disable extension in incognito mode --- package.json | 4 ++-- src/js/background/assignManager.js | 5 +---- src/js/background/badge.js | 15 +++++--------- src/js/background/messageHandler.js | 3 --- src/manifest.json | 32 ++++++++++++++--------------- 5 files changed, 24 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 172a4f5..b72d3d5 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ }, "dependencies": {}, "devDependencies": { - "ajv": "^6.6.2", "addons-linter": "^1.3.2", + "ajv": "^6.6.2", "chai": "^4.1.2", "eslint": "^3.17.1", "eslint-plugin-no-unsanitized": "^2.0.0", @@ -25,7 +25,7 @@ "stylelint": "^7.9.0", "stylelint-config-standard": "^16.0.0", "stylelint-order": "^0.3.0", - "web-ext": "^2.2.2" + "web-ext": "^2.9.3" }, "homepage": "https://github.com/mozilla/multi-account-containers#readme", "license": "MPL-2.0", diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index dc9e991..83acd4b 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -143,7 +143,6 @@ const assignManager = { const userContextId = this.getUserContextIdFromCookieStore(tab); if (!siteSettings || userContextId === siteSettings.userContextId - || tab.incognito || this.storageArea.isExempted(options.url, tab.id)) { return {}; } @@ -289,11 +288,9 @@ const assignManager = { isTabPermittedAssign(tab) { // Ensure we are not an important about url - // Ensure we are not in incognito mode const url = new URL(tab.url); if (url.protocol === "about:" - || url.protocol === "moz-extension:" - || tab.incognito) { + || url.protocol === "moz-extension:") { return false; } return true; diff --git a/src/js/background/badge.js b/src/js/background/badge.js index 78cd9f1..7d532ac 100644 --- a/src/js/background/badge.js +++ b/src/js/background/badge.js @@ -2,22 +2,17 @@ const MAJOR_VERSIONS = ["2.3.0", "2.4.0"]; const badge = { async init() { const currentWindow = await browser.windows.getCurrent(); - this.displayBrowserActionBadge(currentWindow.incognito); - }, - - disableAddon(tabId) { - browser.browserAction.disable(tabId); - browser.browserAction.setTitle({ tabId, title: "Containers disabled in Private Browsing Mode" }); + this.displayBrowserActionBadge(currentWindow); }, async displayBrowserActionBadge() { const extensionInfo = await backgroundLogic.getExtensionInfo(); - const storage = await browser.storage.local.get({browserActionBadgesClicked: []}); + const storage = await browser.storage.local.get({ browserActionBadgesClicked: [] }); if (MAJOR_VERSIONS.indexOf(extensionInfo.version) > -1 && - storage.browserActionBadgesClicked.indexOf(extensionInfo.version) < 0) { - browser.browserAction.setBadgeBackgroundColor({color: "rgba(0,217,0,255)"}); - browser.browserAction.setBadgeText({text: "NEW"}); + storage.browserActionBadgesClicked.indexOf(extensionInfo.version) < 0) { + browser.browserAction.setBadgeBackgroundColor({ color: "rgba(0,217,0,255)" }); + browser.browserAction.setBadgeText({ text: "NEW" }); } } }; diff --git a/src/js/background/messageHandler.js b/src/js/background/messageHandler.js index 9fbe88e..046d163 100644 --- a/src/js/background/messageHandler.js +++ b/src/js/background/messageHandler.js @@ -141,9 +141,6 @@ const messageHandler = { }, {urls: [""], types: ["main_frame"]}); browser.tabs.onCreated.addListener((tab) => { - if (tab.incognito) { - badge.disableAddon(tab.id); - } // lets remember the last tab created so we can close it if it looks like a redirect this.lastCreatedTab = tab; if (tab.cookieStoreId) { diff --git a/src/manifest.json b/src/manifest.json index bab033b..26d2dd8 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -2,22 +2,19 @@ "manifest_version": 2, "name": "Firefox Multi-Account Containers", "version": "6.1.1", - + "incognito": "not_allowed", "description": "Multi-Account Containers helps you keep all the parts of your online life contained in different tabs. Custom labels and color-coded tabs help keep different activities — like online shopping, travel planning, or checking work email — separate.", "icons": { "48": "img/container-site-d-48.png", "96": "img/container-site-d-96.png" }, - "applications": { "gecko": { "id": "@testpilot-containers", - "strict_min_version": "57.0" + "strict_min_version": "67.0" } }, - "homepage_url": "https://github.com/mozilla/multi-account-containers#readme", - "permissions": [ "", "activeTab", @@ -32,7 +29,6 @@ "webRequestBlocking", "webRequest" ], - "commands": { "_execute_browser_action": { "suggested_key": { @@ -42,33 +38,37 @@ "description": "Open containers panel" } }, - "browser_action": { "browser_style": true, "default_icon": "img/container-site.svg", "default_title": "Multi-Account Containers", "default_popup": "popup.html", - "theme_icons": [{ + "theme_icons": [ + { "light": "img/container-site-light.svg", "dark": "img/container-site.svg", "size": 32 - }] + } + ] }, - "background": { "page": "js/background/index.html" }, - "content_scripts": [ { - "matches": [""], - "js": ["js/content-script.js"], - "css": ["css/content.css"], + "matches": [ + "" + ], + "js": [ + "js/content-script.js" + ], + "css": [ + "css/content.css" + ], "run_at": "document_start" } ], - "web_accessible_resources": [ "/img/container-site-d-24.png" ] -} +} \ No newline at end of file From 18bc8eb5aa6b9483cadfa36e656bed48335f1ed1 Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 17 Oct 2019 14:11:59 -0500 Subject: [PATCH 02/13] added bookmark context menu ref: issue #323 --- src/js/background/assignManager.js | 35 +++++++++++++++++++++++++++++- src/manifest.json | 3 ++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index dc9e991..940c906 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -4,6 +4,7 @@ const assignManager = { MENU_SEPARATOR_ID: "separator", MENU_HIDE_ID: "hide-container", MENU_MOVE_ID: "move-to-new-window-container", + OPEN_IN_CONTAINER: "open-link-in-container-tab", storageArea: { area: browser.storage.local, @@ -221,7 +222,11 @@ const assignManager = { init() { browser.contextMenus.onClicked.addListener((info, tab) => { - this._onClickedHandler(info, tab); + if (tab) { + this._onClickedHandler(info, tab); + } else { + this._onClickedBookmark(info); + } }); // Before a request is handled by the browser we decide if we should route through a different container @@ -242,6 +247,8 @@ const assignManager = { } },{urls: [""], types: ["main_frame"]}); + this.initBookmarksMenu(); + }, async _onClickedHandler(info, tab) { @@ -275,6 +282,14 @@ const assignManager = { } }, + async _onClickedBookmark(info) { + const bookmark = await browser.bookmarks.get(info.bookmarkId); + browser.tabs.create({ + cookieStoreId: info.menuItemId, + url: bookmark[0].url + }); + }, + deleteContainer(userContextId) { this.storageArea.deleteContainer(userContextId); @@ -442,6 +457,24 @@ const assignManager = { throw e; }); } + }, + + async initBookmarksMenu() { + browser.contextMenus.create({ + id: this.OPEN_IN_CONTAINER, + title: "Open Link in Container Tab", + contexts: ["bookmark"], + }); + + const identities = await browser.contextualIdentities.query({}); + for (let identity of identities) { // eslint-disable-line prefer-const + browser.contextMenus.create({ + parentId: this.OPEN_IN_CONTAINER, + id: identity.cookieStoreId, + title: identity.name, + icons: { "16": `img/usercontext.svg#${identity.icon}` } + }); + } } }; diff --git a/src/manifest.json b/src/manifest.json index bab033b..54946e0 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -30,7 +30,8 @@ "storage", "tabs", "webRequestBlocking", - "webRequest" + "webRequest", + "bookmarks" ], "commands": { From c4650d12bd74225e6e940ecb0bebe90314369c3e Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 17 Oct 2019 15:25:58 -0500 Subject: [PATCH 03/13] added ability to open folders as well. issue #323 --- src/js/background/assignManager.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 940c906..536e467 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -283,11 +283,16 @@ const assignManager = { }, async _onClickedBookmark(info) { - const bookmark = await browser.bookmarks.get(info.bookmarkId); - browser.tabs.create({ - cookieStoreId: info.menuItemId, - url: bookmark[0].url - }); + let bookmarks = await browser.bookmarks.get(info.bookmarkId); + if (bookmarks[0].type === "folder") { + bookmarks = await browser.bookmarks.getChildren(bookmarks[0].id); + } + for (let bookmark of bookmarks) { // eslint-disable-line prefer-const + browser.tabs.create({ + cookieStoreId: info.menuItemId, + url: bookmark.url + }); + } }, From dae376500bde31ac86860ef65583415a4b6c5bcb Mon Sep 17 00:00:00 2001 From: dnahol Date: Thu, 10 Oct 2019 10:11:04 -0700 Subject: [PATCH 04/13] added right and left arrow shortcuts for container submenu tabs change focus to whole panel element after right arrow press, allows navigation without pressing tab --- src/js/popup.js | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/js/popup.js b/src/js/popup.js index 80986a2..01e792d 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -543,6 +543,7 @@ Logic.registerPanel(P_CONTAINERS_LIST, { previousElement.focus(); } } + switch (e.keyCode) { case 40: next(); @@ -550,6 +551,26 @@ Logic.registerPanel(P_CONTAINERS_LIST, { case 38: previous(); break; + case 39: + { + const showTabs = element.parentNode.querySelector(".show-tabs"); + if(showTabs) { + showTabs.click(); + } + const panel = document.querySelector("html"); + if(panel) { + panel.focus(); + } + break; + } + case 37: + { + const hideTabs = element.parentNode.querySelector(".panel-back-arrow"); + if(hideTabs) { + hideTabs.click(); + } + break; + } default: if ((e.keyCode >= 49 && e.keyCode <= 57) && Logic._currentPanel === "containersList") { @@ -747,7 +768,7 @@ Logic.registerPanel(P_CONTAINER_INFO, { return; } else if (numTabs === 1) { Logic._disableMoveTabs("Cannot move a tab from a single-tab window."); - return; + return; } Logic.addEnterHandler(moveTabsEl, async () => { await browser.runtime.sendMessage({ @@ -808,7 +829,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
${tab.title}
`; tr.querySelector("td").appendChild(Utils.createFavIconElement(tab.favIconUrl)); document.getElementById("container-info-table").appendChild(fragment); - + // On click, we activate this tab. But only if this tab is active. if (!tab.hiddenState) { const closeImage = document.createElement("img"); @@ -842,7 +863,7 @@ Logic.registerPanel(P_CONTAINER_INFO, { }); } } - } + } }, }); @@ -1154,4 +1175,4 @@ window.addEventListener("resize", function () { root.style.setProperty("--overflow-size", difference + "px"); root.style.setProperty("--icon-fit", "12"); } -}); \ No newline at end of file +}); From 9ff1a14e0e20a6779bee4c0bfe78a8019f871316 Mon Sep 17 00:00:00 2001 From: Karskaja Date: Sat, 19 Oct 2019 08:12:51 -0400 Subject: [PATCH 05/13] Fix issue #1041- [Feature request] Open previously hidden tabs in the background Add 'noload' property to openNewTab options, add 'discarded' parameter to browser.tabs.create. New tabs opened from showTabs will be discarded. --- src/js/background/backgroundLogic.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index 52d61a2..ee1bd22 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -55,6 +55,7 @@ const backgroundLogic = { let url = options.url || undefined; const userContextId = ("userContextId" in options) ? options.userContextId : 0; const active = ("nofocus" in options) ? options.nofocus : true; + const discarded = ("noload" in options) ? options.noload : false; const cookieStoreId = backgroundLogic.cookieStoreId(userContextId); // Autofocus url bar will happen in 54: https://bugzilla.mozilla.org/show_bug.cgi?id=1295072 @@ -71,6 +72,7 @@ const backgroundLogic = { return browser.tabs.create({ url, active, + discarded, pinned: options.pinned || false, cookieStoreId }); @@ -313,6 +315,7 @@ const backgroundLogic = { userContextId: userContextId, url: object.url, nofocus: options.nofocus || false, + noload: true, pinned: object.pinned, })); } From c832cf73aa041546c692116fe01aaf96c053ca0b Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Sat, 19 Oct 2019 22:31:12 -0500 Subject: [PATCH 06/13] edits from input --- src/js/background/assignManager.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 536e467..659ecf7 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -4,7 +4,7 @@ const assignManager = { MENU_SEPARATOR_ID: "separator", MENU_HIDE_ID: "hide-container", MENU_MOVE_ID: "move-to-new-window-container", - OPEN_IN_CONTAINER: "open-link-in-container-tab", + OPEN_IN_CONTAINER: "open-bookmark-in-container-tab", storageArea: { area: browser.storage.local, @@ -222,10 +222,10 @@ const assignManager = { init() { browser.contextMenus.onClicked.addListener((info, tab) => { - if (tab) { - this._onClickedHandler(info, tab); - } else { + if (info.bookmarkId) { this._onClickedBookmark(info); + } else { + this._onClickedHandler(info, tab); } }); @@ -467,7 +467,7 @@ const assignManager = { async initBookmarksMenu() { browser.contextMenus.create({ id: this.OPEN_IN_CONTAINER, - title: "Open Link in Container Tab", + title: "Open Bookmark in Container Tab", contexts: ["bookmark"], }); From 7e4950b18444369f62cbff1f49ba154306fff6fb Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Wed, 23 Oct 2019 15:48:43 -0500 Subject: [PATCH 07/13] menu updates when containers are changed, added, or deleted. Tests need to be updated --- src/js/background/assignManager.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 659ecf7..b65f811 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -246,9 +246,30 @@ const assignManager = { delete this.canceledRequests[options.tabId]; } },{urls: [""], types: ["main_frame"]}); - this.initBookmarksMenu(); + browser.contextualIdentities.onCreated.addListener(this.contextualIdentCreated); + browser.contextualIdentities.onUpdated.addListener(this.contextualIdentUpdated); + browser.contextualIdentities.onRemoved.addListener(this.contextualIdentRemoved); + }, + contextualIdentCreated(changeInfo) { + browser.contextMenus.create({ + parentId: assignManager.OPEN_IN_CONTAINER, + id: changeInfo.contextualIdentity.cookieStoreId, + title: changeInfo.contextualIdentity.name, + icons: { "16": `img/usercontext.svg#${changeInfo.contextualIdentity.icon}` } + }); + }, + + contextualIdentUpdated(changeInfo) { + browser.contextMenus.update(changeInfo.contextualIdentity.cookieStoreId, { + title: changeInfo.contextualIdentity.name, + icons: { "16": `img/usercontext.svg#${changeInfo.contextualIdentity.icon}` } + }); + }, + + contextualIdentRemoved(changeInfo) { + browser.contextMenus.remove(changeInfo.contextualIdentity.cookieStoreId); }, async _onClickedHandler(info, tab) { @@ -477,7 +498,7 @@ const assignManager = { parentId: this.OPEN_IN_CONTAINER, id: identity.cookieStoreId, title: identity.name, - icons: { "16": `img/usercontext.svg#${identity.icon}` } + icons: { "16": `img/usercontext.svg#${identity.icon}` } }); } } From e7824f367b34b148ba0598948f0007b37d51bbca Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 24 Oct 2019 14:14:30 -0500 Subject: [PATCH 08/13] added bookmarks as optional_permission and added checkbox in preferences menu. --- src/js/background/assignManager.js | 43 +++++++++++++++++++++------- src/js/background/backgroundLogic.js | 2 +- src/js/background/messageHandler.js | 3 ++ src/js/options.js | 41 ++++++++++++++++++++++++++ src/manifest.json | 11 +++++-- src/options.html | 16 +++++++++++ 6 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 src/js/options.js create mode 100644 src/options.html diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index b65f811..2cdf23c 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -5,7 +5,6 @@ const assignManager = { MENU_HIDE_ID: "hide-container", MENU_MOVE_ID: "move-to-new-window-container", OPEN_IN_CONTAINER: "open-bookmark-in-container-tab", - storageArea: { area: browser.storage.local, exemptedTabs: {}, @@ -222,11 +221,7 @@ const assignManager = { init() { browser.contextMenus.onClicked.addListener((info, tab) => { - if (info.bookmarkId) { - this._onClickedBookmark(info); - } else { - this._onClickedHandler(info, tab); - } + info.bookmarkId ? this._onClickedBookmark(info) : this._onClickedHandler(info, tab); }); // Before a request is handled by the browser we decide if we should route through a different container @@ -246,6 +241,24 @@ const assignManager = { delete this.canceledRequests[options.tabId]; } },{urls: [""], types: ["main_frame"]}); + this.getPermissions(); + }, + + getPermissions() { + browser.permissions.getAll(). + then((permissions) => { + if (permissions.permissions.includes("bookmarks")) { + this.makeBookmarksMenu(); + } else { + browser.contextMenus.remove(this.OPEN_IN_CONTAINER); + } + }). + catch((err) => { + return err.message; + }); + }, + + makeBookmarksMenu() { this.initBookmarksMenu(); browser.contextualIdentities.onCreated.addListener(this.contextualIdentCreated); browser.contextualIdentities.onUpdated.addListener(this.contextualIdentUpdated); @@ -304,11 +317,19 @@ const assignManager = { }, async _onClickedBookmark(info) { - let bookmarks = await browser.bookmarks.get(info.bookmarkId); - if (bookmarks[0].type === "folder") { - bookmarks = await browser.bookmarks.getChildren(bookmarks[0].id); + + async function _getBookmarksFromInfo(info) { + const bookmarkTreeNode = await browser.bookmarks.get(info.bookmarkId); + const firstBookmark = bookmarkTreeNode[0]; + if (firstBookmark.type === "folder") { + return await browser.bookmarks.getChildren(firstBookmark.id); + } else { + return bookmarkTreeNode; + } } - for (let bookmark of bookmarks) { // eslint-disable-line prefer-const + + const bookmarks = await _getBookmarksFromInfo(info); + for (const bookmark of bookmarks) { browser.tabs.create({ cookieStoreId: info.menuItemId, url: bookmark.url @@ -493,7 +514,7 @@ const assignManager = { }); const identities = await browser.contextualIdentities.query({}); - for (let identity of identities) { // eslint-disable-line prefer-const + for (const identity of identities) { browser.contextMenus.create({ parentId: this.OPEN_IN_CONTAINER, id: identity.cookieStoreId, diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index 52d61a2..9857f9e 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -326,4 +326,4 @@ const backgroundLogic = { cookieStoreId(userContextId) { return `firefox-container-${userContextId}`; } -}; +}; \ No newline at end of file diff --git a/src/js/background/messageHandler.js b/src/js/background/messageHandler.js index 9fbe88e..f545389 100644 --- a/src/js/background/messageHandler.js +++ b/src/js/background/messageHandler.js @@ -10,6 +10,9 @@ const messageHandler = { let response; switch (m.method) { + case "resetBookmarksContext": + response = assignManager.getPermissions(); + break; case "deleteContainer": response = backgroundLogic.deleteContainer(m.message.userContextId); break; diff --git a/src/js/options.js b/src/js/options.js new file mode 100644 index 0000000..0eb1bb5 --- /dev/null +++ b/src/js/options.js @@ -0,0 +1,41 @@ + +function requestPermissions() { + const checkbox = document.querySelector("#bookmarksPermissions"); + if (checkbox.checked) { + browser.permissions.request({permissions: ["bookmarks"]}). + then((response) => { + if (response) { + browser.runtime.sendMessage({ method: "resetBookmarksContext" }); + } else { + checkbox.checked = false; + } + }). + catch((err) => { + return err.message; + }); + } else { + browser.permissions.remove({permissions: ["bookmarks"]}). + then(() => { + browser.runtime.sendMessage({ method: "resetBookmarksContext" }); + }). + catch((err) => { + return err.message; + }); + } +} + +function restoreOptions() { + browser.permissions.getAll() + .then((permissions) => { + if (permissions.permissions.includes("bookmarks")) { + document.querySelector("#bookmarksPermissions").checked = true; + } + }). + catch((err) => { + return err.message; + }); +} + + +document.addEventListener("DOMContentLoaded", restoreOptions); +document.querySelector("#bookmarksPermissions").addEventListener( "change", requestPermissions); \ No newline at end of file diff --git a/src/manifest.json b/src/manifest.json index 54946e0..27ce893 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -30,7 +30,10 @@ "storage", "tabs", "webRequestBlocking", - "webRequest", + "webRequest" + ], + + "optional_permissions": [ "bookmarks" ], @@ -71,5 +74,9 @@ "web_accessible_resources": [ "/img/container-site-d-24.png" - ] + ], + + "options_ui": { + "page": "options.html" + } } diff --git a/src/options.html b/src/options.html new file mode 100644 index 0000000..86e3d03 --- /dev/null +++ b/src/options.html @@ -0,0 +1,16 @@ + + + + + + + + +
+ + +

This setting allows you to open a bookmark or folder of bookmarks in a container.

+
+ + + \ No newline at end of file From 1133d48103380305c7cbd3e52def5bb6c360f732 Mon Sep 17 00:00:00 2001 From: dnahol Date: Thu, 24 Oct 2019 14:02:28 -0700 Subject: [PATCH 09/13] left arrow now works without changing focus in right arrow case --- src/js/popup.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/js/popup.js b/src/js/popup.js index 01e792d..401b2bd 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -543,7 +543,6 @@ Logic.registerPanel(P_CONTAINERS_LIST, { previousElement.focus(); } } - switch (e.keyCode) { case 40: next(); @@ -557,15 +556,11 @@ Logic.registerPanel(P_CONTAINERS_LIST, { if(showTabs) { showTabs.click(); } - const panel = document.querySelector("html"); - if(panel) { - panel.focus(); - } break; } case 37: { - const hideTabs = element.parentNode.querySelector(".panel-back-arrow"); + const hideTabs = document.querySelector(".panel-back-arrow"); if(hideTabs) { hideTabs.click(); } From 87a2aa5f1e7a644bae46975c011befeecae0727a Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 24 Oct 2019 16:16:02 -0500 Subject: [PATCH 10/13] added url checks for edge case urls --- src/js/background/assignManager.js | 30 +++++++++++++++++++--------- src/js/background/backgroundLogic.js | 3 --- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 2cdf23c..1a3f527 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -319,21 +319,33 @@ const assignManager = { async _onClickedBookmark(info) { async function _getBookmarksFromInfo(info) { - const bookmarkTreeNode = await browser.bookmarks.get(info.bookmarkId); - const firstBookmark = bookmarkTreeNode[0]; - if (firstBookmark.type === "folder") { - return await browser.bookmarks.getChildren(firstBookmark.id); + const [bookmarkTreeNode] = await browser.bookmarks.get(info.bookmarkId); + if (bookmarkTreeNode.type === "folder") { + return await browser.bookmarks.getChildren(bookmarkTreeNode.id); } else { - return bookmarkTreeNode; + return [bookmarkTreeNode]; } } const bookmarks = await _getBookmarksFromInfo(info); for (const bookmark of bookmarks) { - browser.tabs.create({ - cookieStoreId: info.menuItemId, - url: bookmark.url - }); + // Some checks on the urls from https://github.com/Rob--W/bookmark-container-tab/ thanks! + if ( !/^(javascript|place):/i.test(bookmark.url) && bookmark.type !== "folder") { + const openInReaderMode = bookmark.url.startsWith("about:reader"); + if(openInReaderMode) { + try { + const parsed = new URL(bookmark.url); + bookmark.url = parsed.searchParams.get("url") + parsed.hash; // can't believe const lets me do this ... + } catch (err) { + return err.message; + } + } + browser.tabs.create({ + cookieStoreId: info.menuItemId, + url: bookmark.url, + openInReaderMode: openInReaderMode + }); + } } }, diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index 9857f9e..7556693 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -46,9 +46,6 @@ const backgroundLogic = { donePromise = browser.contextualIdentities.create(options.params); } await donePromise; - browser.runtime.sendMessage({ - method: "refreshNeeded" - }); }, async openNewTab(options) { From bd579fe9076bf18aabfc83850bed4481d62ad5bc Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 24 Oct 2019 16:32:49 -0500 Subject: [PATCH 11/13] added changes requested --- src/js/background/assignManager.js | 30 ++++++++++-------------------- src/options.html | 2 +- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 1a3f527..0559220 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -244,28 +244,19 @@ const assignManager = { this.getPermissions(); }, - getPermissions() { - browser.permissions.getAll(). - then((permissions) => { - if (permissions.permissions.includes("bookmarks")) { - this.makeBookmarksMenu(); - } else { - browser.contextMenus.remove(this.OPEN_IN_CONTAINER); - } - }). - catch((err) => { - return err.message; - }); + async getPermissions() { + const {permissions} = await browser.permissions.getAll() + permissions.includes("bookmarks") ? this.makeBookmarksMenu() : browser.contextMenus.remove(this.OPEN_IN_CONTAINER); }, makeBookmarksMenu() { this.initBookmarksMenu(); - browser.contextualIdentities.onCreated.addListener(this.contextualIdentCreated); - browser.contextualIdentities.onUpdated.addListener(this.contextualIdentUpdated); - browser.contextualIdentities.onRemoved.addListener(this.contextualIdentRemoved); + browser.contextualIdentities.onCreated.addListener(this.contextualIdentityCreated); + browser.contextualIdentities.onUpdated.addListener(this.contextualIdentityUpdated); + browser.contextualIdentities.onRemoved.addListener(this.contextualIdentityRemoved); }, - contextualIdentCreated(changeInfo) { + contextualIdentityCreated(changeInfo) { browser.contextMenus.create({ parentId: assignManager.OPEN_IN_CONTAINER, id: changeInfo.contextualIdentity.cookieStoreId, @@ -274,14 +265,14 @@ const assignManager = { }); }, - contextualIdentUpdated(changeInfo) { + contextualIdentityUpdated(changeInfo) { browser.contextMenus.update(changeInfo.contextualIdentity.cookieStoreId, { title: changeInfo.contextualIdentity.name, icons: { "16": `img/usercontext.svg#${changeInfo.contextualIdentity.icon}` } }); }, - contextualIdentRemoved(changeInfo) { + contextualIdentityRemoved(changeInfo) { browser.contextMenus.remove(changeInfo.contextualIdentity.cookieStoreId); }, @@ -322,9 +313,8 @@ const assignManager = { const [bookmarkTreeNode] = await browser.bookmarks.get(info.bookmarkId); if (bookmarkTreeNode.type === "folder") { return await browser.bookmarks.getChildren(bookmarkTreeNode.id); - } else { - return [bookmarkTreeNode]; } + return [bookmarkTreeNode]; } const bookmarks = await _getBookmarksFromInfo(info); diff --git a/src/options.html b/src/options.html index 86e3d03..84f7353 100644 --- a/src/options.html +++ b/src/options.html @@ -8,7 +8,7 @@
- +

This setting allows you to open a bookmark or folder of bookmarks in a container.

From 6f94ae15007eaa2a719eec4d3665f6efbf633178 Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 24 Oct 2019 16:42:19 -0500 Subject: [PATCH 12/13] updated testing setup to understand my api calls --- src/js/background/assignManager.js | 2 +- test/browser.mock.js | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 0559220..adbc985 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -245,7 +245,7 @@ const assignManager = { }, async getPermissions() { - const {permissions} = await browser.permissions.getAll() + const {permissions} = await browser.permissions.getAll(); permissions.includes("bookmarks") ? this.makeBookmarksMenu() : browser.contextMenus.remove(this.OPEN_IN_CONTAINER); }, diff --git a/test/browser.mock.js b/test/browser.mock.js index d6d38dd..fbff362 100644 --- a/test/browser.mock.js +++ b/test/browser.mock.js @@ -58,7 +58,16 @@ module.exports = () => { contextualIdentities: { create: sinon.stub(), get: sinon.stub(), - query: sinon.stub().resolves([]) + query: sinon.stub().resolves([]), + onCreated: { + addListener: sinon.stub() + }, + onUpdated: { + addListener: sinon.stub() + }, + onRemoved: { + addListener: sinon.stub() + } }, contextMenus: { create: sinon.stub(), @@ -82,6 +91,9 @@ module.exports = () => { }, extension: { getURL: sinon.stub().returns("moz-extension://multi-account-containers/confirm-page.html") + }, + permissions: { + getAll: sinon.stub().returns({"permissions": ["bookmarks"]}) } }; From ef894d847ed15ff1b00a9a00e2da4ad1aac272a4 Mon Sep 17 00:00:00 2001 From: dnahol Date: Thu, 24 Oct 2019 20:25:47 -0700 Subject: [PATCH 13/13] merge upstream commit 'remove HTML entities from tooltip' --- src/js/popup.js | 85 ++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/src/js/popup.js b/src/js/popup.js index 401b2bd..c24d519 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -12,15 +12,15 @@ const NEW_CONTAINER_ID = "new"; const ONBOARDING_STORAGE_KEY = "onboarding-stage"; // List of panels -const P_ONBOARDING_1 = "onboarding1"; -const P_ONBOARDING_2 = "onboarding2"; -const P_ONBOARDING_3 = "onboarding3"; -const P_ONBOARDING_4 = "onboarding4"; -const P_ONBOARDING_5 = "onboarding5"; -const P_CONTAINERS_LIST = "containersList"; -const P_CONTAINERS_EDIT = "containersEdit"; -const P_CONTAINER_INFO = "containerInfo"; -const P_CONTAINER_EDIT = "containerEdit"; +const P_ONBOARDING_1 = "onboarding1"; +const P_ONBOARDING_2 = "onboarding2"; +const P_ONBOARDING_3 = "onboarding3"; +const P_ONBOARDING_4 = "onboarding4"; +const P_ONBOARDING_5 = "onboarding5"; +const P_CONTAINERS_LIST = "containersList"; +const P_CONTAINERS_EDIT = "containersEdit"; +const P_CONTAINER_INFO = "containerInfo"; +const P_CONTAINER_EDIT = "containerEdit"; const P_CONTAINER_DELETE = "containerDelete"; const P_CONTAINERS_ACHIEVEMENT = "containersAchievement"; @@ -32,7 +32,7 @@ const P_CONTAINERS_ACHIEVEMENT = "containersAchievement"; * @return {string} The escaped string. */ function escapeXML(str) { - const replacements = {"&": "&", "\"": """, "'": "'", "<": "<", ">": ">", "/": "/"}; + const replacements = { "&": "&", "\"": """, "'": "'", "<": "<", ">": ">", "/": "/" }; return String(str).replace(/[&"'<>/]/g, m => replacements[m]); } @@ -85,7 +85,7 @@ const Logic = { try { await identitiesPromise; - } catch(e) { + } catch (e) { throw new Error("Failed to retrieve the identities or variation. We cannot continue. ", e.message); } @@ -125,7 +125,7 @@ const Logic = { async showAchievementOrContainersListPanel() { // Do we need to show an achievement panel? let showAchievements = false; - const achievementsStorage = await browser.storage.local.get({achievements: []}); + const achievementsStorage = await browser.storage.local.get({ achievements: [] }); for (const achievement of achievementsStorage.achievements) { if (!achievement.done) { showAchievements = true; @@ -142,7 +142,7 @@ const Logic = { // they have to click the "Done" button to stop the panel // from showing async setAchievementDone(achievementName) { - const achievementsStorage = await browser.storage.local.get({achievements: []}); + const achievementsStorage = await browser.storage.local.get({ achievements: [] }); const achievements = achievementsStorage.achievements; achievements.forEach((achievement, index, achievementsArray) => { if (achievement.name === achievementName) { @@ -150,7 +150,7 @@ const Logic = { achievementsArray[index] = achievement; } }); - browser.storage.local.set({achievements}); + browser.storage.local.set({ achievements }); }, setOnboardingStage(stage) { @@ -161,9 +161,9 @@ const Logic = { async clearBrowserActionBadge() { const extensionInfo = await getExtensionInfo(); - const storage = await browser.storage.local.get({browserActionBadgesClicked: []}); - browser.browserAction.setBadgeBackgroundColor({color: null}); - browser.browserAction.setBadgeText({text: ""}); + const storage = await browser.storage.local.get({ browserActionBadgesClicked: [] }); + browser.browserAction.setBadgeBackgroundColor({ color: null }); + browser.browserAction.setBadgeText({ text: "" }); storage.browserActionBadgesClicked.push(extensionInfo.version); // use set and spread to create a unique array const browserActionBadgesClicked = [...new Set(storage.browserActionBadgesClicked)]; @@ -184,7 +184,7 @@ const Logic = { // Handle old style rejection with null and also Promise.reject new style try { return await browser.contextualIdentities.get(cookieStoreId) || defaultContainer; - } catch(e) { + } catch (e) { return defaultContainer; } }, @@ -207,7 +207,7 @@ const Logic = { }, async currentTab() { - const activeTabs = await browser.tabs.query({active: true, windowId: browser.windows.WINDOW_ID_CURRENT}); + const activeTabs = await browser.tabs.query({ active: true, windowId: browser.windows.WINDOW_ID_CURRENT }); if (activeTabs.length > 0) { return activeTabs[0]; } @@ -215,7 +215,7 @@ const Logic = { }, async numTabs() { - const activeTabs = await browser.tabs.query({windowId: browser.windows.WINDOW_ID_CURRENT}); + const activeTabs = await browser.tabs.query({ windowId: browser.windows.WINDOW_ID_CURRENT }); return activeTabs.length; }, @@ -259,7 +259,7 @@ const Logic = { getPanelSelector(panel) { if (this._onboardingVariation === "securityOnboarding" && - panel.hasOwnProperty("securityPanelSelector")) { + panel.hasOwnProperty("securityPanelSelector")) { return panel.securityPanelSelector; } else { return panel.panelSelector; @@ -289,7 +289,13 @@ const Logic = { } } }); - document.querySelector(this.getPanelSelector(this._panels[panel])).classList.remove("hide"); + const panelEl = document.querySelector(this.getPanelSelector(this._panels[panel])); + panelEl.classList.remove("hide"); + + const focusEl = panelEl.querySelector(".firstTabindex"); + if(focusEl) { + focusEl.focus(); + } }, showPreviousPanel() { @@ -333,7 +339,7 @@ const Logic = { return browser.runtime.sendMessage({ method: "deleteContainer", - message: {userContextId} + message: { userContextId } }); }, @@ -347,7 +353,7 @@ const Logic = { getAssignmentObjectByContainer(userContextId) { return browser.runtime.sendMessage({ method: "getAssignmentObjectByContainer", - message: {userContextId} + message: { userContextId } }); }, @@ -376,7 +382,7 @@ const Logic = { }); // Here we find the first valid id. - for (let id = 1;; ++id) { + for (let id = 1; ; ++id) { if (ids.indexOf(id) === -1) { return defaultName + (id < 10 ? "0" : "") + id; } @@ -511,7 +517,7 @@ Logic.registerPanel(P_CONTAINERS_LIST, { }); Logic.addEnterHandler(document.querySelector("#edit-containers-link"), (e) => { - if (!e.target.classList.contains("disable-edit-containers")){ + if (!e.target.classList.contains("disable-edit-containers")) { Logic.showPanel(P_CONTAINERS_EDIT); } }); @@ -653,9 +659,10 @@ Logic.registerPanel(P_CONTAINERS_LIST, { context.classList.add("userContext-wrapper", "open-newtab", "clickable"); manage.classList.add("show-tabs", "pop-button"); - manage.title = escaped`View ${identity.name} container`; + manage.setAttribute("title", `View ${identity.name} container`); context.setAttribute("tabindex", "0"); - context.title = escaped`Create ${identity.name} tab`; + context.classList.add("firstTabindex"); + context.setAttribute("title", `Create ${identity.name} tab`); context.innerHTML = escaped`
{ if (e.target.matches(".open-newtab") - || e.target.parentNode.matches(".open-newtab") - || e.type === "keydown") { + || e.target.parentNode.matches(".open-newtab") + || e.type === "keydown") { try { browser.tabs.create({ cookieStoreId: identity.cookieStoreId @@ -729,11 +736,15 @@ Logic.registerPanel(P_CONTAINER_INFO, { // This method is called when the object is registered. async initialize() { - Logic.addEnterHandler(document.querySelector("#close-container-info-panel"), () => { + const closeContEl = document.querySelector("#close-container-info-panel"); + closeContEl.setAttribute("tabindex", "0"); + closeContEl.classList.add("firstTabindex"); + Logic.addEnterHandler(closeContEl, () => { Logic.showPreviousPanel(); }); - - Logic.addEnterHandler(document.querySelector("#container-info-hideorshow"), async () => { + const hideContEl = document.querySelector("#container-info-hideorshow"); + hideContEl.setAttribute("tabindex", "0"); + Logic.addEnterHandler(hideContEl, async () => { const identity = Logic.currentIdentity(); try { browser.runtime.sendMessage({ @@ -757,6 +768,7 @@ Logic.registerPanel(P_CONTAINER_INFO, { throw new Error("Could not check for incompatible add-ons."); } const moveTabsEl = document.querySelector("#container-info-movetabs"); + moveTabsEl.setAttribute("tabindex","0"); const numTabs = await Logic.numTabs(); if (incompatible) { Logic._disableMoveTabs("Moving container tabs is incompatible with Pulse, PageShot, and SnoozeTabs."); @@ -823,6 +835,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
${tab.title}
`; tr.querySelector("td").appendChild(Utils.createFavIconElement(tab.favIconUrl)); + tr.setAttribute("tabindex", "0"); document.getElementById("container-info-table").appendChild(fragment); // On click, we activate this tab. But only if this tab is active. @@ -846,7 +859,7 @@ Logic.registerPanel(P_CONTAINER_INFO, { tr.classList.add("clickable"); Logic.addEnterHandler(tr, async () => { - await browser.tabs.update(tab.id, {active: true}); + await browser.tabs.update(tab.id, { active: true }); window.close(); }); @@ -1034,7 +1047,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, { return escaped`