From 18bc8eb5aa6b9483cadfa36e656bed48335f1ed1 Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 17 Oct 2019 14:11:59 -0500 Subject: [PATCH 1/8] 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 2/8] 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 c832cf73aa041546c692116fe01aaf96c053ca0b Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Sat, 19 Oct 2019 22:31:12 -0500 Subject: [PATCH 3/8] 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 4/8] 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 5/8] 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 87a2aa5f1e7a644bae46975c011befeecae0727a Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 24 Oct 2019 16:16:02 -0500 Subject: [PATCH 6/8] 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 7/8] 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 8/8] 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"]}) } };