forked from ZenBrowserMirrors/zen-desktop
feat: Replace zen's tab unloader with firefox's one. Also added more tests, b=(no-bug), c=common, tabs, tests, glance
This commit is contained in:
parent
6f5d20fd49
commit
ebfc885745
24 changed files with 358 additions and 378 deletions
2
l10n
2
l10n
|
@ -1 +1 @@
|
||||||
Subproject commit 4d0df55d514b54626faa1f2fc06eb020feeb7f6d
|
Subproject commit 644474b8c92e306288d835698eb6714081a650d8
|
|
@ -97,10 +97,6 @@ pref('zen.keyboard.shortcuts.disable-mainkeyset-clear', false); // for debugging
|
||||||
|
|
||||||
pref('zen.themes.updated-value-observer', false);
|
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.debug', false);
|
||||||
pref('zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', false);
|
pref('zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', false);
|
||||||
pref('zen.pinned-tab-manager.close-shortcut-behavior', 'reset-unload-switch');
|
pref('zen.pinned-tab-manager.close-shortcut-behavior', 'reset-unload-switch');
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
|
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
|
--- a/browser/base/content/browser.js
|
||||||
+++ b/browser/base/content/browser.js
|
+++ b/browser/base/content/browser.js
|
||||||
@@ -33,6 +33,7 @@ ChromeUtils.defineESModuleGetters(this, {
|
@@ -33,6 +33,7 @@ ChromeUtils.defineESModuleGetters(this, {
|
||||||
|
@ -10,19 +10,18 @@ index 6d664917a5a3bb1cea8a747e42e8bc0065ec999e..7fe04b426a8dd3c8dbb71065da047f8f
|
||||||
DevToolsSocketStatus:
|
DevToolsSocketStatus:
|
||||||
"resource://devtools/shared/security/DevToolsSocketStatus.sys.mjs",
|
"resource://devtools/shared/security/DevToolsSocketStatus.sys.mjs",
|
||||||
DownloadUtils: "resource://gre/modules/DownloadUtils.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);
|
AboutReaderParent.updateReaderButton(gBrowser.selectedBrowser);
|
||||||
TranslationsParent.onLocationChange(gBrowser.selectedBrowser);
|
TranslationsParent.onLocationChange(gBrowser.selectedBrowser);
|
||||||
|
|
||||||
+ gZenViewSplitter.onLocationChange(gBrowser.selectedBrowser);
|
+ gZenViewSplitter.onLocationChange(gBrowser.selectedBrowser);
|
||||||
+ gZenWorkspaces.onLocationChange(gBrowser.selectedBrowser);
|
+ gZenWorkspaces.onLocationChange(gBrowser.selectedBrowser);
|
||||||
+ gZenTabUnloader.onLocationChange(gBrowser.selectedBrowser);
|
|
||||||
+ gZenPinnedTabManager.onLocationChange(gBrowser.selectedBrowser);
|
+ gZenPinnedTabManager.onLocationChange(gBrowser.selectedBrowser);
|
||||||
+
|
+
|
||||||
PictureInPicture.updateUrlbarToggle(gBrowser.selectedBrowser);
|
PictureInPicture.updateUrlbarToggle(gBrowser.selectedBrowser);
|
||||||
|
|
||||||
if (!gMultiProcessBrowser) {
|
if (!gMultiProcessBrowser) {
|
||||||
@@ -4816,7 +4822,7 @@ function switchToTabHavingURI(
|
@@ -4816,7 +4821,7 @@ function switchToTabHavingURI(
|
||||||
ignoreQueryString || replaceQueryString,
|
ignoreQueryString || replaceQueryString,
|
||||||
ignoreFragmentWhenComparing
|
ignoreFragmentWhenComparing
|
||||||
);
|
);
|
||||||
|
@ -31,7 +30,7 @@ index 6d664917a5a3bb1cea8a747e42e8bc0065ec999e..7fe04b426a8dd3c8dbb71065da047f8f
|
||||||
for (let i = 0; i < browsers.length; i++) {
|
for (let i = 0; i < browsers.length; i++) {
|
||||||
let browser = browsers[i];
|
let browser = browsers[i];
|
||||||
let browserCompare = cleanURL(
|
let browserCompare = cleanURL(
|
||||||
@@ -4859,7 +4865,7 @@ function switchToTabHavingURI(
|
@@ -4859,7 +4864,7 @@ function switchToTabHavingURI(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!doAdopt) {
|
if (!doAdopt) {
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
<script src="chrome://browser/content/zen-components/ZenThemesCommon.mjs"></script>
|
<script src="chrome://browser/content/zen-components/ZenThemesCommon.mjs"></script>
|
||||||
<script src="chrome://browser/content/zen-components/ZenThemesImporter.mjs"></script>
|
<script src="chrome://browser/content/zen-components/ZenThemesImporter.mjs"></script>
|
||||||
<script src="chrome://browser/content/zen-components/ZenCompactMode.mjs"></script>
|
<script src="chrome://browser/content/zen-components/ZenCompactMode.mjs"></script>
|
||||||
<script src="chrome://browser/content/zen-components/ZenTabUnloader.mjs"></script>
|
|
||||||
<script src="chrome://browser/content/zen-components/ZenPinnedTabsStorage.mjs"></script>
|
<script src="chrome://browser/content/zen-components/ZenPinnedTabsStorage.mjs"></script>
|
||||||
<script src="chrome://browser/content/zen-components/ZenWorkspacesStorage.mjs"></script>
|
<script src="chrome://browser/content/zen-components/ZenWorkspacesStorage.mjs"></script>
|
||||||
<script src="chrome://browser/content/zen-components/ZenPinnedTabManager.mjs"></script>
|
<script src="chrome://browser/content/zen-components/ZenPinnedTabManager.mjs"></script>
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
|
|
||||||
content/browser/zen-components/ZenKeyboardShortcuts.mjs (../../zen/kbs/ZenKeyboardShortcuts.mjs)
|
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/ZenPinnedTabsStorage.mjs (../../zen/tabs/ZenPinnedTabsStorage.mjs)
|
||||||
content/browser/zen-components/ZenPinnedTabManager.mjs (../../zen/tabs/ZenPinnedTabManager.mjs)
|
content/browser/zen-components/ZenPinnedTabManager.mjs (../../zen/tabs/ZenPinnedTabManager.mjs)
|
||||||
* content/browser/zen-styles/zen-tabs.css (../../zen/tabs/zen-tabs.css)
|
* content/browser/zen-styles/zen-tabs.css (../../zen/tabs/zen-tabs.css)
|
||||||
|
|
|
@ -43,10 +43,6 @@
|
||||||
|
|
||||||
<command id="cmd_zenCopyCurrentURL" />
|
<command id="cmd_zenCopyCurrentURL" />
|
||||||
<command id="cmd_zenCopyCurrentURLMarkdown" />
|
<command id="cmd_zenCopyCurrentURLMarkdown" />
|
||||||
|
|
||||||
<command id="cmd_zenUnloadTab" />
|
|
||||||
<command id="cmd_zenPreventUnloadTab" />
|
|
||||||
<command id="cmd_zenIgnoreUnloadTab" />
|
|
||||||
</commandset>
|
</commandset>
|
||||||
|
|
||||||
<keyset id="zenKeyset"></keyset>
|
<keyset id="zenKeyset"></keyset>
|
||||||
|
|
|
@ -37,18 +37,7 @@
|
||||||
|
|
||||||
<checkbox id="zenTabsUnloadActivate"
|
<checkbox id="zenTabsUnloadActivate"
|
||||||
data-l10n-id="zen-tabs-unloader-enabled"
|
data-l10n-id="zen-tabs-unloader-enabled"
|
||||||
preference="zen.tab-unloader.enabled"/>
|
preference="browser.tabs.unloadOnLowMemory"/>
|
||||||
|
|
||||||
|
|
||||||
<label><html:h2 data-l10n-id="zen-tabs-unloader-unload-delay"/></label>
|
|
||||||
<hbox id="zenTabsUnloadDelayContainer">
|
|
||||||
<description class="description-deemphasized" data-l10n-id="zen-tabs-unloader-unload-delay-description" />
|
|
||||||
<html:input id="zenTabsUnloadDelay"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
max="1000"
|
|
||||||
preference="zen.tab-unloader.timeout-minutes"/>
|
|
||||||
</hbox>
|
|
||||||
</groupbox>
|
</groupbox>
|
||||||
|
|
||||||
<hbox id="zenPinnedTabsManagerCategory"
|
<hbox id="zenPinnedTabsManagerCategory"
|
||||||
|
|
13
src/browser/components/tabbrowser/TabUnloader-sys-mjs.patch
Normal file
13
src/browser/components/tabbrowser/TabUnloader-sys-mjs.patch
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/browser/components/tabbrowser/TabUnloader.sys.mjs b/browser/components/tabbrowser/TabUnloader.sys.mjs
|
||||||
|
index 44846cc902fd3fc17d12be38ac9abccb47a12f23..c715c7cf47486066b3fd6f92bf78bc8a720759bc 100644
|
||||||
|
--- a/browser/components/tabbrowser/TabUnloader.sys.mjs
|
||||||
|
+++ b/browser/components/tabbrowser/TabUnloader.sys.mjs
|
||||||
|
@@ -52,7 +52,7 @@ let CRITERIA_WEIGHT = 1;
|
||||||
|
*/
|
||||||
|
let DefaultTabUnloaderMethods = {
|
||||||
|
isNonDiscardable(tab, weight) {
|
||||||
|
- if (tab.undiscardable || tab.selected) {
|
||||||
|
+ if (tab.undiscardable || tab.selected || tab.zenModeActive) {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
|
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
|
||||||
index d5aa64842a35c6697263c63fd3a0571b64b01344..bcae8a44593d7b3e5efdd999b4c2f5bcac221632 100644
|
index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b032cf200f1 100644
|
||||||
--- a/browser/components/tabbrowser/content/tabbrowser.js
|
--- a/browser/components/tabbrowser/content/tabbrowser.js
|
||||||
+++ b/browser/components/tabbrowser/content/tabbrowser.js
|
+++ b/browser/components/tabbrowser/content/tabbrowser.js
|
||||||
@@ -413,11 +413,41 @@
|
@@ -413,11 +413,41 @@
|
||||||
|
@ -491,17 +491,6 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..bcae8a44593d7b3e5efdd999b4c2f5bc
|
||||||
if (!this._windowIsClosing) {
|
if (!this._windowIsClosing) {
|
||||||
if (wasPinned) {
|
if (wasPinned) {
|
||||||
this.tabContainer._positionPinnedTabs();
|
this.tabContainer._positionPinnedTabs();
|
||||||
@@ -5141,8 +5266,8 @@
|
|
||||||
return closedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
- async explicitUnloadTabs(tabs) {
|
|
||||||
- let unloadBlocked = await this.runBeforeUnloadForTabs(tabs);
|
|
||||||
+ async explicitUnloadTabs(tabs, skipPermitUnload = false) {
|
|
||||||
+ let unloadBlocked = skipPermitUnload ? false : await this.runBeforeUnloadForTabs(tabs);
|
|
||||||
if (unloadBlocked) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -5230,6 +5355,7 @@
|
@@ -5230,6 +5355,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1051,8 +1051,7 @@ menuitem[id='placesContext_new:separator'] {
|
||||||
--menu-image: url('close-all.svg');
|
--menu-image: url('close-all.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
#context_zenUnloadTab,
|
#context_unloadTab,
|
||||||
#context_zenUnloadWebPanel,
|
|
||||||
#context_zenTabActions {
|
#context_zenTabActions {
|
||||||
--menu-image: url('close-all.svg');
|
--menu-image: url('close-all.svg');
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
|
|
||||||
class ZenUIMigration {
|
class ZenUIMigration {
|
||||||
PREF_NAME = 'zen.migration.version';
|
PREF_NAME = 'zen.migration.version';
|
||||||
MIGRATION_VERSION = 3;
|
MIGRATION_VERSION = 4;
|
||||||
|
|
||||||
init(isNewProfile, win) {
|
init(isNewProfile, win) {
|
||||||
if (!isNewProfile) {
|
if (!isNewProfile) {
|
||||||
|
@ -33,6 +33,9 @@ class ZenUIMigration {
|
||||||
if (this._migrationVersion < 3) {
|
if (this._migrationVersion < 3) {
|
||||||
this._migrateV3(win);
|
this._migrateV3(win);
|
||||||
}
|
}
|
||||||
|
if (this._migrationVersion < 4) {
|
||||||
|
this._migrateV4(win);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearVariables() {
|
clearVariables() {
|
||||||
|
@ -82,6 +85,13 @@ class ZenUIMigration {
|
||||||
win.CustomizableUI.removeWidgetFromArea(widgetId);
|
win.CustomizableUI.removeWidgetFromArea(widgetId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_migrateV4(win) {
|
||||||
|
Services.prefs.setBoolPref(
|
||||||
|
'browser.tabs.unloadOnLowMemory',
|
||||||
|
Services.prefs.getBoolPref('zen.tab-unloader.enabled', true)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export var gZenUIMigration = new ZenUIMigration();
|
export var gZenUIMigration = new ZenUIMigration();
|
||||||
|
|
|
@ -88,15 +88,6 @@ document.addEventListener(
|
||||||
case 'cmd_zenRemoveFromEssentials':
|
case 'cmd_zenRemoveFromEssentials':
|
||||||
gZenPinnedTabManager.removeEssentials();
|
gZenPinnedTabManager.removeEssentials();
|
||||||
break;
|
break;
|
||||||
case 'cmd_zenUnloadTab':
|
|
||||||
gZenTabUnloader.unloadTab();
|
|
||||||
break;
|
|
||||||
case 'cmd_zenPreventUnloadTab':
|
|
||||||
gZenTabUnloader.preventUnloadTab();
|
|
||||||
break;
|
|
||||||
case 'cmd_zenIgnoreUnloadTab':
|
|
||||||
gZenTabUnloader.ignoreUnloadTab();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
if (event.target.id.startsWith('cmd_zenWorkspaceSwitch')) {
|
if (event.target.id.startsWith('cmd_zenWorkspaceSwitch')) {
|
||||||
const index = parseInt(event.target.id.replace('cmd_zenWorkspaceSwitch', ''), 10) - 1;
|
const index = parseInt(event.target.id.replace('cmd_zenWorkspaceSwitch', ''), 10) - 1;
|
||||||
|
|
|
@ -397,10 +397,10 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onTabClick(e) {
|
async _onTabClick(e) {
|
||||||
const tab = e.target?.closest('tab');
|
const tab = e.target?.closest('tab');
|
||||||
if (e.button === 1 && tab) {
|
if (e.button === 1 && tab) {
|
||||||
this._onCloseTabShortcut(e, tab);
|
await this._onCloseTabShortcut(e, tab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onCloseTabShortcut(
|
async _onCloseTabShortcut(
|
||||||
event,
|
event,
|
||||||
selectedTab = gBrowser.selectedTab,
|
selectedTab = gBrowser.selectedTab,
|
||||||
behavior = lazy.zenPinnedTabCloseShortcutBehavior
|
behavior = lazy.zenPinnedTabCloseShortcutBehavior
|
||||||
|
@ -554,22 +554,17 @@
|
||||||
case 'unload-switch':
|
case 'unload-switch':
|
||||||
case 'reset-switch':
|
case 'reset-switch':
|
||||||
case 'switch':
|
case 'switch':
|
||||||
let { permitUnload } = selectedTab.linkedBrowser?.permitUnload();
|
|
||||||
if (!permitUnload) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._handleTabSwitch(selectedTab);
|
|
||||||
if (behavior.includes('reset')) {
|
|
||||||
this._resetTabToStoredState(selectedTab);
|
|
||||||
}
|
|
||||||
if (behavior.includes('unload')) {
|
if (behavior.includes('unload')) {
|
||||||
if (selectedTab.hasAttribute('glance-id')) {
|
if (selectedTab.hasAttribute('glance-id')) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Do not unload about:* pages
|
await gBrowser.explicitUnloadTabs([selectedTab]);
|
||||||
if (!selectedTab.linkedBrowser?.currentURI.spec.startsWith('about:')) {
|
}
|
||||||
gZenTabUnloader.explicitUnloadTabs([selectedTab], { permitUnload });
|
if (selectedTab.selected) {
|
||||||
}
|
this._handleTabSwitch(selectedTab);
|
||||||
|
}
|
||||||
|
if (behavior.includes('reset')) {
|
||||||
|
this._resetTabToStoredState(selectedTab);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'reset':
|
case 'reset':
|
||||||
|
|
|
@ -1,310 +0,0 @@
|
||||||
{
|
|
||||||
const lazy = {};
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(
|
|
||||||
lazy,
|
|
||||||
'zenTabUnloaderEnabled',
|
|
||||||
'zen.tab-unloader.enabled',
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(
|
|
||||||
lazy,
|
|
||||||
'zenTabUnloaderTimeout',
|
|
||||||
'zen.tab-unloader.timeout-minutes',
|
|
||||||
20
|
|
||||||
);
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(
|
|
||||||
lazy,
|
|
||||||
'zenTabUnloaderExcludedUrls',
|
|
||||||
'zen.tab-unloader.excluded-urls',
|
|
||||||
''
|
|
||||||
);
|
|
||||||
|
|
||||||
const ZEN_TAB_UNLOADER_DEFAULT_EXCLUDED_URLS = [
|
|
||||||
'^about:',
|
|
||||||
'^chrome:',
|
|
||||||
'^devtools:',
|
|
||||||
'^file:',
|
|
||||||
'^resource:',
|
|
||||||
'^view-source:',
|
|
||||||
'^view-image:',
|
|
||||||
];
|
|
||||||
|
|
||||||
class ZenTabsObserver {
|
|
||||||
static ALL_EVENTS = [
|
|
||||||
'TabAttrModified',
|
|
||||||
'TabPinned',
|
|
||||||
'TabUnpinned',
|
|
||||||
'TabShow',
|
|
||||||
'TabHide',
|
|
||||||
'TabOpen',
|
|
||||||
'TabClose',
|
|
||||||
'TabSelect',
|
|
||||||
'TabMultiSelect',
|
|
||||||
];
|
|
||||||
|
|
||||||
#listeners = [];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.#listenAllEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
#listenAllEvents() {
|
|
||||||
const eventListener = this.#eventListener.bind(this);
|
|
||||||
for (const event of ZenTabsObserver.ALL_EVENTS) {
|
|
||||||
window.addEventListener(event, eventListener);
|
|
||||||
}
|
|
||||||
window.addEventListener('unload', () => {
|
|
||||||
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();
|
|
||||||
}
|
|
|
@ -8,3 +8,4 @@ support-files = [
|
||||||
["browser_glance_close.js"]
|
["browser_glance_close.js"]
|
||||||
["browser_glance_next_tab.js"]
|
["browser_glance_next_tab.js"]
|
||||||
["browser_glance_prev_tab.js"]
|
["browser_glance_prev_tab.js"]
|
||||||
|
["browser_glance_select_parent.js"]
|
||||||
|
|
23
src/zen/tests/glance/browser_glance_select_parent.js
Normal file
23
src/zen/tests/glance/browser_glance_select_parent.js
Normal file
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
|
@ -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_changed.js"]
|
||||||
["browser_pinned_created.js"]
|
["browser_pinned_created.js"]
|
||||||
["browser_pinned_edit_label.js"]
|
["browser_pinned_edit_label.js"]
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
add_task(async function test_Create_Pinned() {
|
add_task(async function test_Changed_Pinned() {
|
||||||
let resolvePromise;
|
let resolvePromise;
|
||||||
const promise = new Promise((resolve) => {
|
const promise = new Promise((resolve) => {
|
||||||
resolvePromise = resolve;
|
resolvePromise = resolve;
|
||||||
|
|
34
src/zen/tests/pinned/browser_pinned_close.js
Normal file
34
src/zen/tests/pinned/browser_pinned_close.js
Normal file
|
@ -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;
|
||||||
|
});
|
||||||
|
});
|
51
src/zen/tests/pinned/browser_pinned_nounload_reset.js
Normal file
51
src/zen/tests/pinned/browser_pinned_nounload_reset.js
Normal file
|
@ -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;
|
||||||
|
});
|
||||||
|
});
|
51
src/zen/tests/pinned/browser_pinned_reset_noswitch.js
Normal file
51
src/zen/tests/pinned/browser_pinned_reset_noswitch.js
Normal file
|
@ -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;
|
||||||
|
});
|
||||||
|
});
|
51
src/zen/tests/pinned/browser_pinned_switch.js
Normal file
51
src/zen/tests/pinned/browser_pinned_switch.js
Normal file
|
@ -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;
|
||||||
|
});
|
||||||
|
});
|
49
src/zen/tests/pinned/browser_pinned_unload_changed.js
Normal file
49
src/zen/tests/pinned/browser_pinned_unload_changed.js
Normal file
|
@ -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;
|
||||||
|
});
|
||||||
|
});
|
48
src/zen/tests/pinned/browser_pinned_unload_noreset.js
Normal file
48
src/zen/tests/pinned/browser_pinned_unload_noreset.js
Normal file
|
@ -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;
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue