From ffbb740445c1a2d8a7222486e2c9d2b65e64837a Mon Sep 17 00:00:00 2001 From: Rafee Date: Thu, 1 Aug 2024 13:58:16 -0400 Subject: [PATCH 1/5] feat #303: reset cookies in site manager --- src/_locales | 2 +- src/css/popup.css | 20 ++++++++++++++++---- src/js/background/assignManager.js | 12 ++++++++++++ src/js/background/messageHandler.js | 3 +++ src/js/popup.js | 11 ++++++++++- src/js/utils.js | 8 ++++++++ 6 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/_locales b/src/_locales index d330106..93c87c7 160000 --- a/src/_locales +++ b/src/_locales @@ -1 +1 @@ -Subproject commit d3301069f51262e8cf493a86aa2785cf3261141e +Subproject commit 93c87c7aa80d7709d5263de1d39468b675720d94 diff --git a/src/css/popup.css b/src/css/popup.css index 5980894..d3b5f6c 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -228,6 +228,7 @@ body { /* Hack for menu icons to use a light color without affecting container icons */ [data-theme="light"] img.delete-assignment, +[data-theme="dark"] img.reset-assignment, [data-theme="dark"] .trash-button, [data-theme="dark"] img.menu-icon, [data-theme="dark"] .menu-icon > img, @@ -287,7 +288,7 @@ table { /* effect borrowed from tabs in firefox, ensure that the element flexes to the full width */ .truncate-text { - inline-size: calc(100vw - 80px); + inline-size: calc(100vw - 100px); overflow: hidden; position: relative; white-space: nowrap; @@ -2314,7 +2315,8 @@ input { * rules grouped together at the beginning of the file */ /* stylelint-disable no-descending-specificity */ -.trash-button { +.trash-button, +.reset-button { display: inline-block; block-size: 20px; inline-size: 20px; @@ -2323,11 +2325,21 @@ input { text-align: center; } -tr > td > .trash-button { +.reset-button { + margin-right: 8px; +} + +.tooltip-wrapper:hover .site-settings-tooltip { + display: block; +} + +tr > td > .trash-button, +tr > td > .reset-button { display: none; } -tr:hover > td > .trash-button { +tr:hover > td > .trash-button, +tr:hover > td > .reset-button { display: block; } diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 1226cba..80a2325 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -571,6 +571,18 @@ window.assignManager = { return true; }, + async _resetCookiesForSite(pageUrl, cookieStoreId) { + const url = new URL(pageUrl); + // Remove 'www.' from the domain value + const domain = url.hostname.replace(/^www\./, ""); + const cookies = await browser.cookies.getAll({domain: domain, storeId: cookieStoreId}); + for (const cookie of cookies) { + const domain = cookie.domain.startsWith(".") ? cookie.domain.slice(1) : cookie.domain; + const cookieUrl = `${cookie.secure ? "https" : "http"}://${domain}${cookie.path}`; + await browser.cookies.remove({ url: cookieUrl, name: cookie.name, storeId: cookie.storeId }); + } + }, + async _setOrRemoveAssignment(tabId, pageUrl, userContextId, remove) { let actionName; // https://github.com/mozilla/testpilot-containers/issues/626 diff --git a/src/js/background/messageHandler.js b/src/js/background/messageHandler.js index 5d644b6..bb58895 100644 --- a/src/js/background/messageHandler.js +++ b/src/js/background/messageHandler.js @@ -45,6 +45,9 @@ const messageHandler = { // m.url is the assignment to be removed/added response = assignManager._setOrRemoveAssignment(m.tabId, m.url, m.userContextId, m.value); break; + case "resetCookiesForSite": + response = assignManager._resetCookiesForSite(m.pageUrl, m.cookieStoreId); + break; case "sortTabs": backgroundLogic.sortTabs(); break; diff --git a/src/js/popup.js b/src/js/popup.js index 236e393..bba41ea 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -1450,11 +1450,14 @@ Logic.registerPanel(P_CONTAINER_ASSIGNMENTS, { /* As we don't have the full or correct path the best we can assume is the path is HTTPS and then replace with a broken icon later if it doesn't load. This is pending a better solution for favicons from web extensions */ const assumedUrl = `https://${site.hostname}/favicon.ico`; + const resetSiteCookiesInfo = browser.i18n.getMessage("resetSiteCookiesTooltipInfo"); + const deleteSiteInfo = browser.i18n.getMessage("deleteSiteTooltipInfo"); trElement.innerHTML = Utils.escaped`
${site.hostname} - + + `; trElement.getElementsByClassName("favicon")[0].appendChild(Utils.createFavIconElement(assumedUrl)); const deleteButton = trElement.querySelector(".trash-button"); @@ -1466,6 +1469,12 @@ Logic.registerPanel(P_CONTAINER_ASSIGNMENTS, { delete assignments[siteKey]; this.showAssignedContainers(assignments); }); + const resetButton = trElement.querySelector(".reset-button"); + Utils.addEnterHandler(resetButton, async () => { + const pageUrl = `https://${site.hostname}`; + const cookieStoreId = Logic.currentCookieStoreId(); + Utils.resetCookiesForSite(pageUrl, cookieStoreId); + }); trElement.classList.add("menu-item", "hover-highlight", "keyboard-nav"); tableElement.appendChild(trElement); }); diff --git a/src/js/utils.js b/src/js/utils.js index f1932ac..5745a47 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -138,6 +138,14 @@ const Utils = { }); }, + resetCookiesForSite(pageUrl, cookieStoreId) { + return browser.runtime.sendMessage({ + method: "resetCookiesForSite", + pageUrl, + cookieStoreId, + }); + }, + async reloadInContainer(url, currentUserContextId, newUserContextId, tabIndex, active) { return await browser.runtime.sendMessage({ method: "reloadInContainer", From 606e08d2b7288cd268dc0ef0d50eca38eb858967 Mon Sep 17 00:00:00 2001 From: Rafee Date: Tue, 20 Aug 2024 13:47:36 -0400 Subject: [PATCH 2/5] feat #303: Container storage deletion and confirmation popup --- src/_locales | 2 +- src/css/popup.css | 23 +++++++++++++++++++ src/js/background/assignManager.js | 2 ++ src/js/background/backgroundLogic.js | 15 ++++++++++++ src/js/background/messageHandler.js | 3 +++ src/js/popup.js | 34 +++++++++++++++++++++++++++- src/manifest.json | 1 + src/popup.html | 15 ++++++++++++ 8 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/_locales b/src/_locales index 93c87c7..c640d40 160000 --- a/src/_locales +++ b/src/_locales @@ -1 +1 @@ -Subproject commit 93c87c7aa80d7709d5263de1d39468b675720d94 +Subproject commit c640d4062a5f3da3608d28d9928be614d6bc4fb9 diff --git a/src/css/popup.css b/src/css/popup.css index d3b5f6c..d2cbdae 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -237,6 +237,7 @@ body { filter: invert(1); } +[data-theme="dark"] img.clear-storage-icon, [data-theme="dark"] img.delete-assignment, [data-theme="dark"] #edit-sites-assigned .menu-icon, [data-theme="dark"] #container-info-table .menu-icon { @@ -286,6 +287,28 @@ table { display: none !important; } +.popup-notification-card { + opacity: 0; + pointer-events: none; + transition: opacity 2s; + border-radius: 4px; + font-size: 12px; + position: absolute; + top: 0; + left: 0; + padding: 8px; + margin: 8px; + inline-size: calc(100vw - 25px); + background-color: var(--button-bg-active-color-secondary); + z-index: 3; +} + +.is-shown { + pointer-events: auto; + opacity: 1; + transition: opacity 0s; +} + /* effect borrowed from tabs in firefox, ensure that the element flexes to the full width */ .truncate-text { inline-size: calc(100vw - 100px); diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 80a2325..bdbd367 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -581,6 +581,8 @@ window.assignManager = { const cookieUrl = `${cookie.secure ? "https" : "http"}://${domain}${cookie.path}`; await browser.cookies.remove({ url: cookieUrl, name: cookie.name, storeId: cookie.storeId }); } + + return true; // Success }, async _setOrRemoveAssignment(tabId, pageUrl, userContextId, remove) { diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index 5d9f576..448b1e3 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -75,6 +75,21 @@ const backgroundLogic = { return extensionInfo; }, + // Remove container data (cookies, localStorage and cache) + async deleteContainerDataOnly(userContextId) { + await this._closeTabs(userContextId); + + await browser.browsingData.removeCookies({ + cookieStoreId: this.cookieStoreId(userContextId) + }); + + await browser.browsingData.removeLocalStorage({ + cookieStoreId: this.cookieStoreId(userContextId) + }); + + return {done: true, userContextId}; + }, + getUserContextIdFromCookieStoreId(cookieStoreId) { if (!cookieStoreId) { return false; diff --git a/src/js/background/messageHandler.js b/src/js/background/messageHandler.js index bb58895..c7bce82 100644 --- a/src/js/background/messageHandler.js +++ b/src/js/background/messageHandler.js @@ -23,6 +23,9 @@ const messageHandler = { case "deleteContainer": response = backgroundLogic.deleteContainer(m.message.userContextId); break; + case "deleteContainerDataOnly": + response = backgroundLogic.deleteContainerDataOnly(m.message.userContextId); + break; case "createOrUpdateContainer": response = backgroundLogic.createOrUpdateContainer(m.message); break; diff --git a/src/js/popup.js b/src/js/popup.js index bba41ea..99bcdcf 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -122,6 +122,19 @@ const Logic = { }, + notify(i18nOpts) { + const notificationCards = document.querySelectorAll(".popup-notification-card"); + const text = browser.i18n.getMessage(i18nOpts.messageId, i18nOpts.placeholders); + notificationCards.forEach(notificationCard => { + notificationCard.textContent = text; + notificationCard.classList.add("is-shown"); + + setTimeout(() => { + notificationCard.classList.remove("is-shown"); + }, 1000); + }); + }, + async showAchievementOrContainersListPanel() { // Do we need to show an achievement panel? let showAchievements = false; @@ -966,6 +979,20 @@ Logic.registerPanel(P_CONTAINER_INFO, { Utils.alwaysOpenInContainer(identity); window.close(); }); + + const deleteData = document.querySelector("#delete-data-info-panel"); + Utils.addEnterHandler(deleteData, async () => { + const userContextId = Utils.userContextId(identity.cookieStoreId) + + await browser.runtime.sendMessage({ + method: "deleteContainerDataOnly", + message: { userContextId } + }); + + Logic.notify({messageId: "storageWasClearedConfirmation", placeholders: [identity.name]}); + this.prepare(); + }); + // Show or not the has-tabs section. for (let trHasTabs of document.getElementsByClassName("container-info-has-tabs")) { // eslint-disable-line prefer-const trHasTabs.style.display = !identity.hasHiddenTabs && !identity.hasOpenTabs ? "none" : ""; @@ -1473,7 +1500,12 @@ Logic.registerPanel(P_CONTAINER_ASSIGNMENTS, { Utils.addEnterHandler(resetButton, async () => { const pageUrl = `https://${site.hostname}`; const cookieStoreId = Logic.currentCookieStoreId(); - Utils.resetCookiesForSite(pageUrl, cookieStoreId); + const result = await Utils.resetCookiesForSite(pageUrl, cookieStoreId); + if (result === true) { + Logic.notify({messageId: "cookieResetSuccess", placeholders: []}); + } else { + Logic.notify({messageId: "cookiesCouldNotBeReset", placeholders: []}); + } }); trElement.classList.add("menu-item", "hover-highlight", "keyboard-nav"); tableElement.appendChild(trElement); diff --git a/src/manifest.json b/src/manifest.json index 21d3d0b..eeaf5a9 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -13,6 +13,7 @@ "", "activeTab", "cookies", + "browsingData", "contextMenus", "contextualIdentities", "history", diff --git a/src/popup.html b/src/popup.html index fac21fe..046ba5a 100644 --- a/src/popup.html +++ b/src/popup.html @@ -107,6 +107,7 @@