diff --git a/l10n b/l10n
index 4d0df55d..644474b8 160000
--- a/l10n
+++ b/l10n
@@ -1 +1 @@
-Subproject commit 4d0df55d514b54626faa1f2fc06eb020feeb7f6d
+Subproject commit 644474b8c92e306288d835698eb6714081a650d8
diff --git a/src/browser/app/profile/features.inc b/src/browser/app/profile/features.inc
index 6c34fa16..c9d70b80 100644
--- a/src/browser/app/profile/features.inc
+++ b/src/browser/app/profile/features.inc
@@ -97,10 +97,6 @@ pref('zen.keyboard.shortcuts.disable-mainkeyset-clear', false); // for debugging
pref('zen.themes.updated-value-observer', false);
-pref('zen.tab-unloader.enabled', true);
-pref('zen.tab-unloader.timeout-minutes', 40);
-pref('zen.tab-unloader.excluded-urls', "example.com,example.org");
-
pref('zen.pinned-tab-manager.debug', false);
pref('zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', false);
pref('zen.pinned-tab-manager.close-shortcut-behavior', 'reset-unload-switch');
diff --git a/src/browser/base/content/browser-js.patch b/src/browser/base/content/browser-js.patch
index 44612588..7baa95e0 100644
--- a/src/browser/base/content/browser-js.patch
+++ b/src/browser/base/content/browser-js.patch
@@ -1,5 +1,5 @@
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
-index 6d664917a5a3bb1cea8a747e42e8bc0065ec999e..7fe04b426a8dd3c8dbb71065da047f8f48b8e84c 100644
+index 6d664917a5a3bb1cea8a747e42e8bc0065ec999e..5059293ebfa29d646455b7a3505bd6eae408ba64 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -33,6 +33,7 @@ ChromeUtils.defineESModuleGetters(this, {
@@ -10,19 +10,18 @@ index 6d664917a5a3bb1cea8a747e42e8bc0065ec999e..7fe04b426a8dd3c8dbb71065da047f8f
DevToolsSocketStatus:
"resource://devtools/shared/security/DevToolsSocketStatus.sys.mjs",
DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
-@@ -2340,6 +2341,11 @@ var XULBrowserWindow = {
+@@ -2340,6 +2341,10 @@ var XULBrowserWindow = {
AboutReaderParent.updateReaderButton(gBrowser.selectedBrowser);
TranslationsParent.onLocationChange(gBrowser.selectedBrowser);
+ gZenViewSplitter.onLocationChange(gBrowser.selectedBrowser);
+ gZenWorkspaces.onLocationChange(gBrowser.selectedBrowser);
-+ gZenTabUnloader.onLocationChange(gBrowser.selectedBrowser);
+ gZenPinnedTabManager.onLocationChange(gBrowser.selectedBrowser);
+
PictureInPicture.updateUrlbarToggle(gBrowser.selectedBrowser);
if (!gMultiProcessBrowser) {
-@@ -4816,7 +4822,7 @@ function switchToTabHavingURI(
+@@ -4816,7 +4821,7 @@ function switchToTabHavingURI(
ignoreQueryString || replaceQueryString,
ignoreFragmentWhenComparing
);
@@ -31,7 +30,7 @@ index 6d664917a5a3bb1cea8a747e42e8bc0065ec999e..7fe04b426a8dd3c8dbb71065da047f8f
for (let i = 0; i < browsers.length; i++) {
let browser = browsers[i];
let browserCompare = cleanURL(
-@@ -4859,7 +4865,7 @@ function switchToTabHavingURI(
+@@ -4859,7 +4864,7 @@ function switchToTabHavingURI(
}
if (!doAdopt) {
diff --git a/src/browser/base/content/zen-assets.inc.xhtml b/src/browser/base/content/zen-assets.inc.xhtml
index ed982342..449855cb 100644
--- a/src/browser/base/content/zen-assets.inc.xhtml
+++ b/src/browser/base/content/zen-assets.inc.xhtml
@@ -34,7 +34,6 @@
-
diff --git a/src/browser/base/content/zen-assets.jar.inc.mn b/src/browser/base/content/zen-assets.jar.inc.mn
index b083e20e..96ac35a4 100644
--- a/src/browser/base/content/zen-assets.jar.inc.mn
+++ b/src/browser/base/content/zen-assets.jar.inc.mn
@@ -50,7 +50,6 @@
content/browser/zen-components/ZenKeyboardShortcuts.mjs (../../zen/kbs/ZenKeyboardShortcuts.mjs)
- content/browser/zen-components/ZenTabUnloader.mjs (../../zen/tabs/ZenTabUnloader.mjs)
content/browser/zen-components/ZenPinnedTabsStorage.mjs (../../zen/tabs/ZenPinnedTabsStorage.mjs)
content/browser/zen-components/ZenPinnedTabManager.mjs (../../zen/tabs/ZenPinnedTabManager.mjs)
* content/browser/zen-styles/zen-tabs.css (../../zen/tabs/zen-tabs.css)
diff --git a/src/browser/base/content/zen-keysets.inc.xhtml b/src/browser/base/content/zen-keysets.inc.xhtml
index 1b3c25f2..5efa7c2c 100644
--- a/src/browser/base/content/zen-keysets.inc.xhtml
+++ b/src/browser/base/content/zen-keysets.inc.xhtml
@@ -43,10 +43,6 @@
-
-
-
-
diff --git a/src/browser/components/preferences/zenTabsManagement.inc.xhtml b/src/browser/components/preferences/zenTabsManagement.inc.xhtml
index 6c6e9295..d5405953 100644
--- a/src/browser/components/preferences/zenTabsManagement.inc.xhtml
+++ b/src/browser/components/preferences/zenTabsManagement.inc.xhtml
@@ -37,18 +37,7 @@
-
-
-
-
-
-
-
+ preference="browser.tabs.unloadOnLowMemory"/>
{
- for (const event of ZenTabsObserver.ALL_EVENTS) {
- window.removeEventListener(event, eventListener);
- }
- });
- }
-
- #eventListener(event) {
- for (const listener of this.#listeners) {
- listener(event.type, event);
- }
- }
-
- addTabsListener(listener) {
- this.#listeners.push(listener);
- }
- }
-
- class ZenTabsIntervalUnloader {
- static INTERVAL = 1000 * 60; // 1 minute
-
- interval = null;
- /** @type {ZenTabUnloader} */
- unloader = null;
-
- constructor(unloader) {
- this.unloader = unloader;
- this.interval = setInterval(
- this.intervalListener.bind(this),
- ZenTabsIntervalUnloader.INTERVAL
- );
- }
-
- intervalListener() {
- if (!lazy.zenTabUnloaderEnabled) {
- return;
- }
- const currentTimestamp = Date.now();
- const tabs = gZenWorkspaces.allStoredTabs;
- for (let i = 0; i < tabs.length; i++) {
- const tab = tabs[i];
- if (this.unloader.canUnloadTab(tab, currentTimestamp)) {
- this.unloader.unload(tab);
- }
- }
- }
- }
-
- class ZenTabUnloader extends ZenDOMOperatedFeature {
- static ACTIVITY_MODIFIERS = ['muted', 'soundplaying', 'label', 'attention'];
-
- #excludedUrls = [];
- #compiledExcludedUrls = [];
- #lastCheckedUrlTimestamp = 0;
-
- constructor() {
- super();
-
- this.#excludedUrls = this.lazyExcludeUrls;
- if (!lazy.zenTabUnloaderEnabled) {
- return;
- }
- this.intervalUnloader = new ZenTabsIntervalUnloader(this);
- }
-
- init() {
- if (!lazy.zenTabUnloaderEnabled) {
- return;
- }
- this.observer = new ZenTabsObserver();
- this.observer.addTabsListener(this.onTabEvent.bind(this));
- }
-
- onTabEvent(action, event) {
- const tab = event.target;
- switch (action) {
- case 'TabPinned':
- case 'TabUnpinned':
- case 'TabShow':
- case 'TabHide':
- break;
- case 'TabAttrModified':
- this.handleTabAttrModified(tab, event);
- break;
- case 'TabOpen':
- this.handleTabOpen(tab);
- break;
- case 'TabClose':
- this.handleTabClose(tab);
- break;
- case 'TabSelect':
- case 'TabMultiSelect':
- this.updateTabActivity(tab);
- break;
- default:
- console.warn('ZenTabUnloader: Unhandled tab event', action);
- break;
- }
- }
-
- onLocationChange(browser) {
- const tab = browser.ownerGlobal.gBrowser.getTabForBrowser(browser);
- this.updateTabActivity(tab);
- }
-
- handleTabClose(tab) {
- tab.lastActivity = null;
- }
-
- handleTabOpen(tab) {
- this.updateTabActivity(tab);
- }
-
- handleTabAttrModified(tab, event) {
- for (const modifier of ZenTabUnloader.ACTIVITY_MODIFIERS) {
- if (event.detail.changed.includes(modifier)) {
- this.updateTabActivity(tab);
- break;
- }
- }
- }
-
- updateTabActivity(tab) {
- const currentTimestamp = Date.now();
- tab.lastActivity = currentTimestamp;
- }
-
- get lazyExcludeUrls() {
- return [
- ...ZEN_TAB_UNLOADER_DEFAULT_EXCLUDED_URLS,
- ...lazy.zenTabUnloaderExcludedUrls.split(',').map((url) => url.trim()),
- ];
- }
-
- arraysEqual(a, b) {
- if (a === b) return true;
- if (a == null || b == null) return false;
- if (a.length !== b.length) return false;
-
- const currentTimestamp = Date.now();
- if (currentTimestamp - this.#lastCheckedUrlTimestamp < 5 * 1000) {
- return true;
- }
-
- this.#lastCheckedUrlTimestamp = currentTimestamp;
- // If you don't care about the order of the elements inside
- // the array, you should sort both arrays here.
- // Please note that calling sort on an array will modify that array.
- // you might want to clone your array first.
-
- for (let i = 0; i < a.length; ++i) {
- if (a[i] !== b[i]) return false;
- }
- return true;
- }
-
- get excludedUrls() {
- // Check if excludedrls is the same as the pref value
- const excludedUrls = this.lazyExcludeUrls;
- if (
- !this.arraysEqual(this.#excludedUrls, excludedUrls) ||
- !this.#compiledExcludedUrls.length
- ) {
- this.#excludedUrls = excludedUrls;
- this.#compiledExcludedUrls = excludedUrls.map((url) => new RegExp(url));
- }
- return this.#compiledExcludedUrls;
- }
-
- unload(tab, skipPermitUnload = false) {
- gBrowser.explicitUnloadTabs([tab], skipPermitUnload);
- tab.removeAttribute('linkedpanel');
- }
-
- unloadTab() {
- const tabs = TabContextMenu.contextTab.multiselected
- ? gBrowser.selectedTabs
- : [TabContextMenu.contextTab];
- this.explicitUnloadTabs(tabs);
- }
-
- explicitUnloadTabs(tabs, extraArgs = {}) {
- for (let i = 0; i < tabs.length; i++) {
- if (this.canUnloadTab(tabs[i], Date.now(), true, extraArgs)) {
- this.unload(tabs[i], true);
- }
- }
- }
-
- preventUnloadTab() {
- const tabs = TabContextMenu.contextTab.multiselected
- ? gBrowser.selectedTabs
- : [TabContextMenu.contextTab];
- for (let i = 0; i < tabs.length; i++) {
- const tab = tabs[i];
- tab.zenIgnoreUnload = true;
- }
- }
-
- ignoreUnloadTab() {
- const tabs = TabContextMenu.contextTab.multiselected
- ? gBrowser.selectedTabs
- : [TabContextMenu.contextTab];
- for (let i = 0; i < tabs.length; i++) {
- const tab = tabs[i];
- tab.zenIgnoreUnload = false;
- }
- }
-
- canUnloadTab(tab, currentTimestamp, ignoreTimestamp = false, extraArgs = {}) {
- if (
- (tab.pinned && !ignoreTimestamp) ||
- tab.selected ||
- (tab.multiselected && !ignoreTimestamp) ||
- (tab.hasAttribute('busy') && !ignoreTimestamp) ||
- !tab.linkedPanel ||
- tab.splitView ||
- tab.group?.hasAttribute('split-view-group') ||
- tab.attention ||
- tab.hasAttribute('glance-id') ||
- tab.linkedBrowser?.zenModeActive ||
- (tab.pictureinpicture && !ignoreTimestamp) ||
- (tab.soundPlaying && !ignoreTimestamp) ||
- (tab.zenIgnoreUnload && !ignoreTimestamp) ||
- (this.excludedUrls.some((url) => url.test(tab.linkedBrowser?.currentURI.spec)) &&
- tab.linkedBrowser?.currentURI.spec !== 'about:blank')
- ) {
- return false;
- }
- if (ignoreTimestamp) {
- return this._tabPermitsUnload(tab, extraArgs);
- }
- const lastActivity = tab.lastActivity;
- if (!lastActivity) {
- return false;
- }
- const diff = currentTimestamp - lastActivity;
- // Check if the tab has been inactive for more than the timeout
- return (
- diff > lazy.zenTabUnloaderTimeout * 60 * 1000 && this._tabPermitsUnload(tab, extraArgs)
- );
- }
-
- _tabPermitsUnload(tab, extraArgs) {
- return typeof extraArgs.permitUnload === 'undefined'
- ? tab.linkedBrowser?.permitUnload()?.permitUnload
- : extraArgs.permitUnload;
- }
- }
-
- window.gZenTabUnloader = new ZenTabUnloader();
-}
diff --git a/src/zen/tests/glance/browser.toml b/src/zen/tests/glance/browser.toml
index 035b9220..8de9e9e1 100644
--- a/src/zen/tests/glance/browser.toml
+++ b/src/zen/tests/glance/browser.toml
@@ -8,3 +8,4 @@ support-files = [
["browser_glance_close.js"]
["browser_glance_next_tab.js"]
["browser_glance_prev_tab.js"]
+["browser_glance_select_parent.js"]
diff --git a/src/zen/tests/glance/browser_glance_select_parent.js b/src/zen/tests/glance/browser_glance_select_parent.js
new file mode 100644
index 00000000..29b55ac6
--- /dev/null
+++ b/src/zen/tests/glance/browser_glance_select_parent.js
@@ -0,0 +1,23 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+'use strict';
+
+add_task(async function test_Glance_Select_Parent() {
+ await openGlanceOnTab(async (glanceTab) => {
+ ok(
+ glanceTab.hasAttribute('zen-glance-tab'),
+ 'The glance tab should have the zen-glance-tab attribute'
+ );
+ await BrowserTestUtils.openNewForegroundTab(window.gBrowser, 'https://example.com/', true, {
+ skipAnimation: true,
+ });
+ const tabToRemove = gBrowser.selectedTab;
+ gBrowser.selectedTab = gZenGlanceManager.getTabOrGlanceParent(glanceTab);
+ await BrowserTestUtils.waitForCondition(() => {
+ return glanceTab.selected;
+ });
+ ok(true, 'The glance tab should be selected');
+ await BrowserTestUtils.removeTab(tabToRemove);
+ });
+});
diff --git a/src/zen/tests/pinned/browser.toml b/src/zen/tests/pinned/browser.toml
index e07b1951..f3adcb07 100644
--- a/src/zen/tests/pinned/browser.toml
+++ b/src/zen/tests/pinned/browser.toml
@@ -1,3 +1,10 @@
+
+["browser_pinned_unload_changed.js"]
+["browser_pinned_unload_noreset.js"]
+["browser_pinned_nounload_reset.js"]
+["browser_pinned_switch.js"]
+["browser_pinned_reset_noswitch.js"]
+["browser_pinned_close.js"]
["browser_pinned_changed.js"]
["browser_pinned_created.js"]
["browser_pinned_edit_label.js"]
diff --git a/src/zen/tests/pinned/browser_pinned_changed.js b/src/zen/tests/pinned/browser_pinned_changed.js
index beee3a6f..576c1694 100644
--- a/src/zen/tests/pinned/browser_pinned_changed.js
+++ b/src/zen/tests/pinned/browser_pinned_changed.js
@@ -3,7 +3,7 @@
'use strict';
-add_task(async function test_Create_Pinned() {
+add_task(async function test_Changed_Pinned() {
let resolvePromise;
const promise = new Promise((resolve) => {
resolvePromise = resolve;
diff --git a/src/zen/tests/pinned/browser_pinned_close.js b/src/zen/tests/pinned/browser_pinned_close.js
new file mode 100644
index 00000000..c3c009ae
--- /dev/null
+++ b/src/zen/tests/pinned/browser_pinned_close.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+'use strict';
+
+add_task(async function test_Unload_NoReset_Pinned() {
+ await SpecialPowers.pushPrefEnv({
+ set: [['zen.pinned-tab-manager.close-shortcut-behavior', 'close']],
+ });
+
+ let resolvePromise;
+ const promise = new Promise((resolve) => {
+ resolvePromise = resolve;
+ });
+
+ await BrowserTestUtils.withNewTab({ gBrowser, url: 'https://example.com/1' }, async (browser) => {
+ const tab = gBrowser.getTabForBrowser(browser);
+ tab.addEventListener(
+ 'ZenPinnedTabCreated',
+ async function (event) {
+ const pinTabID = tab.getAttribute('zen-pin-id');
+ ok(pinTabID, 'The tab should have a zen-pin-id attribute after being pinned');
+ document.getElementById('cmd_close').doCommand();
+ setTimeout(() => {
+ ok(tab.closing, 'The tab should be closing after being closed');
+ resolvePromise();
+ }, 100);
+ },
+ { once: true }
+ );
+ gBrowser.pinTab(tab);
+ await promise;
+ });
+});
diff --git a/src/zen/tests/pinned/browser_pinned_nounload_reset.js b/src/zen/tests/pinned/browser_pinned_nounload_reset.js
new file mode 100644
index 00000000..9930b026
--- /dev/null
+++ b/src/zen/tests/pinned/browser_pinned_nounload_reset.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+'use strict';
+
+add_task(async function test_NoUnload_Changed_Pinned() {
+ await SpecialPowers.pushPrefEnv({
+ set: [['zen.pinned-tab-manager.close-shortcut-behavior', 'reset-switch']],
+ });
+
+ let resolvePromise;
+ const promise = new Promise((resolve) => {
+ resolvePromise = resolve;
+ });
+
+ await BrowserTestUtils.withNewTab({ gBrowser, url: 'https://example.com/1' }, async (browser) => {
+ const tab = gBrowser.getTabForBrowser(browser);
+ tab.addEventListener(
+ 'ZenPinnedTabCreated',
+ async function (event) {
+ const pinTabID = tab.getAttribute('zen-pin-id');
+ ok(pinTabID, 'The tab should have a zen-pin-id attribute after being pinned');
+
+ BrowserTestUtils.startLoadingURIString(browser, 'https://example.com/2');
+ await BrowserTestUtils.browserLoaded(browser, false, 'https://example.com/2');
+ setTimeout(() => {
+ ok(
+ tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should have a zen-pinned-changed attribute after being pinned'
+ );
+ document.getElementById('cmd_close').doCommand();
+ setTimeout(() => {
+ ok(
+ !tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should not have a zen-pinned-changed attribute after being closed'
+ );
+ ok(
+ !tab.hasAttribute('discarded'),
+ 'The tab should not be discarded after being closed'
+ );
+ ok(tab != gBrowser.selectedTab, 'The tab should not be selected after being closed');
+ resolvePromise();
+ }, 100);
+ }, 0);
+ },
+ { once: true }
+ );
+ gBrowser.pinTab(tab);
+ await promise;
+ });
+});
diff --git a/src/zen/tests/pinned/browser_pinned_reset_noswitch.js b/src/zen/tests/pinned/browser_pinned_reset_noswitch.js
new file mode 100644
index 00000000..969e68f3
--- /dev/null
+++ b/src/zen/tests/pinned/browser_pinned_reset_noswitch.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+'use strict';
+
+add_task(async function test_Unload_NoReset_Pinned() {
+ await SpecialPowers.pushPrefEnv({
+ set: [['zen.pinned-tab-manager.close-shortcut-behavior', 'reset']],
+ });
+
+ let resolvePromise;
+ const promise = new Promise((resolve) => {
+ resolvePromise = resolve;
+ });
+
+ await BrowserTestUtils.withNewTab({ gBrowser, url: 'https://example.com/1' }, async (browser) => {
+ const tab = gBrowser.getTabForBrowser(browser);
+ tab.addEventListener(
+ 'ZenPinnedTabCreated',
+ async function (event) {
+ const pinTabID = tab.getAttribute('zen-pin-id');
+ ok(pinTabID, 'The tab should have a zen-pin-id attribute after being pinned');
+
+ BrowserTestUtils.startLoadingURIString(browser, 'https://example.com/2');
+ await BrowserTestUtils.browserLoaded(browser, false, 'https://example.com/2');
+ setTimeout(() => {
+ ok(
+ tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should have a zen-pinned-changed attribute after being pinned'
+ );
+ document.getElementById('cmd_close').doCommand();
+ setTimeout(() => {
+ ok(
+ !tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should not have a zen-pinned-changed attribute after being closed'
+ );
+ ok(
+ !tab.hasAttribute('discarded'),
+ 'The tab should not be discarded after being closed'
+ );
+ ok(tab === gBrowser.selectedTab, 'The tab should not be selected after being closed');
+ resolvePromise();
+ }, 100);
+ }, 0);
+ },
+ { once: true }
+ );
+ gBrowser.pinTab(tab);
+ await promise;
+ });
+});
diff --git a/src/zen/tests/pinned/browser_pinned_switch.js b/src/zen/tests/pinned/browser_pinned_switch.js
new file mode 100644
index 00000000..d0a2caa5
--- /dev/null
+++ b/src/zen/tests/pinned/browser_pinned_switch.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+'use strict';
+
+add_task(async function test_Unload_NoReset_Pinned() {
+ await SpecialPowers.pushPrefEnv({
+ set: [['zen.pinned-tab-manager.close-shortcut-behavior', 'switch']],
+ });
+
+ let resolvePromise;
+ const promise = new Promise((resolve) => {
+ resolvePromise = resolve;
+ });
+
+ await BrowserTestUtils.withNewTab({ gBrowser, url: 'https://example.com/1' }, async (browser) => {
+ const tab = gBrowser.getTabForBrowser(browser);
+ tab.addEventListener(
+ 'ZenPinnedTabCreated',
+ async function (event) {
+ const pinTabID = tab.getAttribute('zen-pin-id');
+ ok(pinTabID, 'The tab should have a zen-pin-id attribute after being pinned');
+
+ BrowserTestUtils.startLoadingURIString(browser, 'https://example.com/2');
+ await BrowserTestUtils.browserLoaded(browser, false, 'https://example.com/2');
+ setTimeout(() => {
+ ok(
+ tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should have a zen-pinned-changed attribute after being pinned'
+ );
+ document.getElementById('cmd_close').doCommand();
+ setTimeout(() => {
+ ok(
+ tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should not have a zen-pinned-changed attribute after being closed'
+ );
+ ok(
+ !tab.hasAttribute('discarded'),
+ 'The tab should not be discarded after being closed'
+ );
+ ok(tab != gBrowser.selectedTab, 'The tab should not be selected after being closed');
+ resolvePromise();
+ }, 100);
+ }, 0);
+ },
+ { once: true }
+ );
+ gBrowser.pinTab(tab);
+ await promise;
+ });
+});
diff --git a/src/zen/tests/pinned/browser_pinned_unload_changed.js b/src/zen/tests/pinned/browser_pinned_unload_changed.js
new file mode 100644
index 00000000..5d7bc6f5
--- /dev/null
+++ b/src/zen/tests/pinned/browser_pinned_unload_changed.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+'use strict';
+
+add_task(async function test_Unload_Changed_Pinned() {
+ await SpecialPowers.pushPrefEnv({
+ set: [['zen.pinned-tab-manager.close-shortcut-behavior', 'reset-unload-switch']],
+ });
+
+ let resolvePromise;
+ const promise = new Promise((resolve) => {
+ resolvePromise = resolve;
+ });
+
+ await BrowserTestUtils.withNewTab({ gBrowser, url: 'https://example.com/1' }, async (browser) => {
+ const tab = gBrowser.getTabForBrowser(browser);
+ tab.addEventListener(
+ 'ZenPinnedTabCreated',
+ async function (event) {
+ const pinTabID = tab.getAttribute('zen-pin-id');
+ ok(pinTabID, 'The tab should have a zen-pin-id attribute after being pinned');
+
+ BrowserTestUtils.startLoadingURIString(browser, 'https://example.com/2');
+ await BrowserTestUtils.browserLoaded(browser, false, 'https://example.com/2');
+ setTimeout(() => {
+ ok(
+ tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should have a zen-pinned-changed attribute after being pinned'
+ );
+ document.getElementById('cmd_close').doCommand();
+ setTimeout(() => {
+ ok(
+ !tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should not have a zen-pinned-changed attribute after being closed'
+ );
+
+ ok(tab.hasAttribute('discarded'), 'The tab should not be discarded after being closed');
+ ok(tab != gBrowser.selectedTab, 'The tab should not be selected after being closed');
+ resolvePromise();
+ }, 100);
+ }, 0);
+ },
+ { once: true }
+ );
+ gBrowser.pinTab(tab);
+ await promise;
+ });
+});
diff --git a/src/zen/tests/pinned/browser_pinned_unload_noreset.js b/src/zen/tests/pinned/browser_pinned_unload_noreset.js
new file mode 100644
index 00000000..538c84ba
--- /dev/null
+++ b/src/zen/tests/pinned/browser_pinned_unload_noreset.js
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+'use strict';
+
+add_task(async function test_Unload_NoReset_Pinned() {
+ await SpecialPowers.pushPrefEnv({
+ set: [['zen.pinned-tab-manager.close-shortcut-behavior', 'unload-switch']],
+ });
+
+ let resolvePromise;
+ const promise = new Promise((resolve) => {
+ resolvePromise = resolve;
+ });
+
+ await BrowserTestUtils.withNewTab({ gBrowser, url: 'https://example.com/1' }, async (browser) => {
+ const tab = gBrowser.getTabForBrowser(browser);
+ tab.addEventListener(
+ 'ZenPinnedTabCreated',
+ async function (event) {
+ const pinTabID = tab.getAttribute('zen-pin-id');
+ ok(pinTabID, 'The tab should have a zen-pin-id attribute after being pinned');
+
+ BrowserTestUtils.startLoadingURIString(browser, 'https://example.com/2');
+ await BrowserTestUtils.browserLoaded(browser, false, 'https://example.com/2');
+ setTimeout(() => {
+ ok(
+ tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should have a zen-pinned-changed attribute after being pinned'
+ );
+ document.getElementById('cmd_close').doCommand();
+ setTimeout(() => {
+ ok(
+ tab.hasAttribute('zen-pinned-changed'),
+ 'The tab should not have a zen-pinned-changed attribute after being closed'
+ );
+ ok(tab.hasAttribute('discarded'), 'The tab should not be discarded after being closed');
+ ok(tab != gBrowser.selectedTab, 'The tab should not be selected after being closed');
+ resolvePromise();
+ }, 100);
+ }, 0);
+ },
+ { once: true }
+ );
+ gBrowser.pinTab(tab);
+ await promise;
+ });
+});