diff --git a/src/browser/base/content/browser-init-js.patch b/src/browser/base/content/browser-init-js.patch index b8ec53782..69de60ba6 100644 --- a/src/browser/base/content/browser-init-js.patch +++ b/src/browser/base/content/browser-init-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js -index bcbfab4a3781ff3c7349115751b3830976eec4bf..8176656b6f5e70ccf3766ad9f5406758fdb7034b 100644 +index bcbfab4a3781ff3c7349115751b3830976eec4bf..b1b774e0d335ed3c5ca565a45cd624c7ea2718af 100644 --- a/browser/base/content/browser-init.js +++ b/browser/base/content/browser-init.js @@ -186,6 +186,7 @@ var gBrowserInit = { @@ -10,3 +10,11 @@ index bcbfab4a3781ff3c7349115751b3830976eec4bf..8176656b6f5e70ccf3766ad9f5406758 gBrowser.addEventListener("DOMUpdateBlockedPopups", e => PopupBlockerObserver.handleEvent(e) ); +@@ -344,6 +345,7 @@ var gBrowserInit = { + + this._handleURIToLoad(); + ++ gZenWorkspaces.selectStartPage(); + Services.obs.addObserver(gIdentityHandler, "perm-changed"); + Services.obs.addObserver(gRemoteControl, "devtools-socket"); + Services.obs.addObserver(gRemoteControl, "marionette-listening"); diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 5564fc2af..f8a009de8 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d82270206683470e4f 100644 +index d5aa64842a35c6697263c63fd3a0571b64b01344..adf3d7c318196a8a02158dfaf9d4d91bf07fdb93 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -413,11 +413,41 @@ @@ -493,16 +493,15 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 } else { TabBarVisibility.update(); } -@@ -5016,6 +5124,8 @@ +@@ -5016,6 +5124,7 @@ this.tabs[i]._tPos = i; } + gZenWorkspaces.updateTabsContainers(); -+ if (!this._windowIsClosing) { if (wasPinned) { this.tabContainer._positionPinnedTabs(); -@@ -5230,6 +5340,7 @@ +@@ -5230,6 +5339,7 @@ } let excludeTabs = new Set(aExcludeTabs); @@ -510,7 +509,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 // If this tab has a successor, it should be selectable, since // hiding or closing a tab removes that tab as a successor. -@@ -5242,13 +5353,13 @@ +@@ -5242,13 +5352,13 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -526,7 +525,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 ); let tab = this.tabContainer.findNextTab(aTab, { -@@ -5264,7 +5375,7 @@ +@@ -5264,7 +5374,7 @@ } if (tab) { @@ -535,7 +534,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 } // If no qualifying visible tab was found, see if there is a tab in -@@ -5285,7 +5396,7 @@ +@@ -5285,7 +5395,7 @@ }); } @@ -544,7 +543,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 } _blurTab(aTab) { -@@ -5686,10 +5797,10 @@ +@@ -5686,10 +5796,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -557,7 +556,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5909,7 +6020,7 @@ +@@ -5909,7 +6019,7 @@ * `true` if element is a `` */ isTabGroup(element) { @@ -566,7 +565,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 } /** -@@ -5986,7 +6097,7 @@ +@@ -5986,7 +6096,7 @@ // Don't allow mixing pinned and unpinned tabs. if (this.isTab(element) && element.pinned) { @@ -575,7 +574,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 } else { tabIndex = Math.max(tabIndex, this.pinnedTabCount); } -@@ -6012,10 +6123,16 @@ +@@ -6012,10 +6122,16 @@ this.#handleTabMove( element, () => { @@ -594,7 +593,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 if (neighbor && this.isTab(element) && tabIndex > element._tPos) { neighbor.after(element); } else { -@@ -6084,17 +6201,29 @@ +@@ -6084,17 +6200,29 @@ targetElement = targetElement.group; } } @@ -628,7 +627,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 if (element.pinned && this.tabContainer.verticalMode) { return this.tabContainer.verticalPinnedTabsContainer; } -@@ -6154,7 +6283,7 @@ +@@ -6154,7 +6282,7 @@ if (!this.isTab(aTab)) { throw new Error("Can only move a tab into a tab group"); } @@ -637,7 +636,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -6248,6 +6377,10 @@ +@@ -6248,6 +6376,10 @@ moveActionCallback(); @@ -648,7 +647,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -7145,7 +7278,7 @@ +@@ -7145,7 +7277,7 @@ // preventDefault(). It will still raise the window if appropriate. break; } @@ -657,7 +656,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 window.focus(); aEvent.preventDefault(); break; -@@ -8044,6 +8177,7 @@ +@@ -8044,6 +8176,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -665,7 +664,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -9009,7 +9143,7 @@ var TabContextMenu = { +@@ -9009,7 +9142,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !this.multiselected; @@ -674,7 +673,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..c9a0a404324ae0ae139f92d822702066 // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -9278,6 +9412,7 @@ var TabContextMenu = { +@@ -9278,6 +9411,7 @@ var TabContextMenu = { telemetrySource: gBrowser.TabMetrics.METRIC_SOURCE.TAB_STRIP, }); } else { diff --git a/src/zen/tabs/ZenPinnedTabManager.mjs b/src/zen/tabs/ZenPinnedTabManager.mjs index 392c53331..8788a2917 100644 --- a/src/zen/tabs/ZenPinnedTabManager.mjs +++ b/src/zen/tabs/ZenPinnedTabManager.mjs @@ -126,17 +126,13 @@ } get enabled() { - if (typeof this._enabled === 'undefined') { - this._enabled = !( - PrivateBrowsingUtils.isWindowPrivate(window) || - document.documentElement.getAttribute('chromehidden')?.includes('toolbar') || - document.documentElement.getAttribute('chromehidden')?.includes('menubar') - ); - } - return this._enabled && !gZenWorkspaces.privateWindowOrDisabled; + return !gZenWorkspaces.privateWindowOrDisabled; } async refreshPinnedTabs({ init = false } = {}) { + if (!this.enabled) { + return; + } await ZenPinnedTabsStorage.promiseInitialized; await gZenWorkspaces.promiseSectionsInitialized; await this._initializePinsCache(); diff --git a/src/zen/tests/glance/browser_glance_next_tab.js b/src/zen/tests/glance/browser_glance_next_tab.js index ce006bad0..5e24340af 100644 --- a/src/zen/tests/glance/browser_glance_next_tab.js +++ b/src/zen/tests/glance/browser_glance_next_tab.js @@ -12,7 +12,14 @@ add_task(async function test_Glance_Next_Tab() { gBrowser.selectedTab = selectedTab; await openGlanceOnTab(async (glanceTab) => { gBrowser.tabContainer.advanceSelectedTab(1); - Assert.equal(gBrowser.selectedTab, tabToCheck, 'Next glance tab should equal'); + const nextTab = gBrowser.selectedTab; + gBrowser.selectedTab = glanceTab; + await new Promise((resolve) => { + setTimeout(() => { + Assert.equal(nextTab, tabToCheck, 'Next glance tab should equal'); + resolve(); + }); + }); }); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); diff --git a/src/zen/tests/glance/browser_glance_prev_tab.js b/src/zen/tests/glance/browser_glance_prev_tab.js index 5ff1cd723..762e944db 100644 --- a/src/zen/tests/glance/browser_glance_prev_tab.js +++ b/src/zen/tests/glance/browser_glance_prev_tab.js @@ -11,7 +11,14 @@ add_task(async function test_Glance_Prev_Tab() { const tabToCheck = gBrowser.selectedTab; gBrowser.selectedTab = glanceTab; gBrowser.tabContainer.advanceSelectedTab(-1); - Assert.equal(gBrowser.selectedTab, tabToCheck, 'Previous glance tab should equal'); + const prevTab = gBrowser.selectedTab; + gBrowser.selectedTab = glanceTab; + await new Promise((resolve) => { + setTimeout(() => { + Assert.equal(prevTab, tabToCheck, 'Previous glance tab should equal'); + resolve(); + }); + }); await BrowserTestUtils.removeTab(tabToCheck); }); }); diff --git a/src/zen/tests/glance/head.js b/src/zen/tests/glance/head.js index c3604d540..640d83031 100644 --- a/src/zen/tests/glance/head.js +++ b/src/zen/tests/glance/head.js @@ -17,17 +17,19 @@ function openGlanceOnTab(callback, close = true) { .then(async (glanceTab) => { await callback(glanceTab); if (close) { - gZenGlanceManager - .closeGlance({ - onTabClose: true, - }) - .then(() => { - resolve(); - }); + setTimeout(() => { + gZenGlanceManager + .closeGlance({ + onTabClose: true, + }) + .then(() => { + resolve(); + }); + }, 500); // Give tons of time for the glance to close } else { resolve(); } }); - }); + }, 500); // Give tons of time for the glance to open }); } diff --git a/src/zen/tests/pinned/browser.toml b/src/zen/tests/pinned/browser.toml index 6a6e4dea1..fd78aab36 100644 --- a/src/zen/tests/pinned/browser.toml +++ b/src/zen/tests/pinned/browser.toml @@ -13,5 +13,8 @@ ["browser_pinned_reordered.js"] ["browser_pinned_to_essential.js"] +["browser_private_mode_no_essentials.js"] +["browser_private_mode_no_ctx_menu.js"] + ["browser_issue_7654.js"] ["browser_issue_8726.js"] diff --git a/src/zen/tests/pinned/browser_private_mode_no_ctx_menu.js b/src/zen/tests/pinned/browser_private_mode_no_ctx_menu.js new file mode 100644 index 000000000..2974005bb --- /dev/null +++ b/src/zen/tests/pinned/browser_private_mode_no_ctx_menu.js @@ -0,0 +1,32 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +'use strict'; + +add_task(async function test_Private_Mode_No_Essentials() { + let privateWindow = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + await privateWindow.gZenWorkspaces.promiseInitialized; + await BrowserTestUtils.openNewForegroundTab(privateWindow.gBrowser, 'https://example.com/', true); + + await new Promise((resolve) => { + privateWindow.gBrowser.selectedTab.addEventListener('popupshown', function (event) { + ok( + privateWindow.document.getElementById('context_zen-add-essentials').hidden, + 'Context menu should not show Zen Essentials option in private mode' + ); + + ok( + privateWindow.document.getElementById('context_pinTab').hidden, + 'Context menu should not show Pin Tab option in private mode' + ); + }); + + EventUtils.synthesizeMouseAtCenter(privateWindow.gBrowser.selectedTab, { + type: 'contextmenu', + }); + }); + + await BrowserTestUtils.closeWindow(privateWindow); +}); diff --git a/src/zen/tests/pinned/browser_private_mode_no_essentials.js b/src/zen/tests/pinned/browser_private_mode_no_essentials.js new file mode 100644 index 000000000..06b178289 --- /dev/null +++ b/src/zen/tests/pinned/browser_private_mode_no_essentials.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_Private_Mode_No_Essentials() { + await BrowserTestUtils.openNewForegroundTab(window.gBrowser, 'https://example.com/', true); + let resolvePromise; + const promise = new Promise((resolve) => { + resolvePromise = resolve; + }); + + const newTab = gBrowser.selectedTab; + newTab.addEventListener( + 'ZenPinnedTabCreated', + async function (event) { + ok(newTab.pinned, 'The tab should be pinned after calling gBrowser.pinTab()'); + + const pinTabID = newTab.getAttribute('zen-pin-id'); + ok(pinTabID, 'The tab should have a zen-pin-id attribute after being pinned'); + + try { + const pins = await ZenPinnedTabsStorage.getPins(); + const pinObject = pins.find((pin) => pin.uuid === pinTabID); + ok(pinObject, 'The pin object should exist in the ZenPinnedTabsStorage'); + + let privateWindow = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + await privateWindow.gZenWorkspaces.promiseInitialized; + ok( + !privateWindow.gBrowser.tabs.some((tab) => tab.pinned), + 'Private window should not have any pinned tabs initially' + ); + + await BrowserTestUtils.closeWindow(privateWindow); + } catch (error) { + ok(false, 'Error while checking the pin object in ZenPinnedTabsStorage: ' + error); + } + resolvePromise(); + }, + { once: true } + ); + gZenPinnedTabManager.addToEssentials(newTab); + + await promise; + await BrowserTestUtils.removeTab(newTab); +}); diff --git a/src/zen/tests/workspaces/browser.toml b/src/zen/tests/workspaces/browser.toml index 12d4c9027..1cc57677b 100644 --- a/src/zen/tests/workspaces/browser.toml +++ b/src/zen/tests/workspaces/browser.toml @@ -7,4 +7,6 @@ support-files = [ ["browser_workspace_bookmarks.js"] ["browser_double_click_newtab.js"] ["browser_overflow_scrollbox.js"] + ["browser_private_mode.js"] +["browser_private_mode_startup.js"] diff --git a/src/zen/tests/workspaces/browser_private_mode.js b/src/zen/tests/workspaces/browser_private_mode.js index 1bc02d42b..3c889bee5 100644 --- a/src/zen/tests/workspaces/browser_private_mode.js +++ b/src/zen/tests/workspaces/browser_private_mode.js @@ -3,7 +3,7 @@ 'use strict'; -add_task(async function testPrivateMode() { +add_task(async function test_Private_Mode() { await SpecialPowers.pushPrefEnv({ set: [['privacy.userContext.enabled', true]], }); diff --git a/src/zen/tests/workspaces/browser_private_mode_startup.js b/src/zen/tests/workspaces/browser_private_mode_startup.js new file mode 100644 index 000000000..c964207a8 --- /dev/null +++ b/src/zen/tests/workspaces/browser_private_mode_startup.js @@ -0,0 +1,22 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +'use strict'; + +add_task(async function test_Private_Mode_Startup() { + let privateWindow = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + await privateWindow.gZenWorkspaces.promiseInitialized; + await new Promise((resolve) => { + setTimeout(() => { + Assert.equal( + privateWindow.gBrowser.tabs.length, + 1, + 'Private window should start with one tab' + ); + resolve(); + }, 1000); + }); + await BrowserTestUtils.closeWindow(privateWindow); +}); diff --git a/src/zen/workspaces/ZenGradientGenerator.mjs b/src/zen/workspaces/ZenGradientGenerator.mjs index daa540124..f65004661 100644 --- a/src/zen/workspaces/ZenGradientGenerator.mjs +++ b/src/zen/workspaces/ZenGradientGenerator.mjs @@ -1106,9 +1106,14 @@ let workspaceTheme = theme || workspace.theme; await this.foreachWindowAsActive(async (browser) => { + if (!browser.gZenThemePicker.promiseInitialized) { + return; + } + if (browser.closing || (await browser.gZenThemePicker?.promiseInitialized)) { return; } + // Do not rebuild if the workspace is not the same as the current one const windowWorkspace = await browser.gZenWorkspaces.getActiveWorkspace(); if (windowWorkspace.uuid !== uuid && theme !== null) { diff --git a/src/zen/workspaces/ZenWorkspaces.mjs b/src/zen/workspaces/ZenWorkspaces.mjs index 31e0aae52..bbd35c7cd 100644 --- a/src/zen/workspaces/ZenWorkspaces.mjs +++ b/src/zen/workspaces/ZenWorkspaces.mjs @@ -854,7 +854,6 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature { await this.workspaceBookmarks(); await gZenPinnedTabManager.refreshPinnedTabs({ init: true }); await this.changeWorkspace(activeWorkspace, { onInit: true }); - await this.#selectStartPage(); this._fixTabPositions(); this._resolveInitialized(); this._clearAnyZombieTabs(); // Dont call with await @@ -871,10 +870,11 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature { window.addEventListener('TabBrowserInserted', this.onTabBrowserInserted.bind(this)); } - async #selectStartPage() { - if (gZenUIManager.testingEnabled) { + async selectStartPage() { + if (gZenUIManager.testingEnabled || !this.workspaceEnabled) { return; } + await this.promiseInitialized; let showed = false; let resolveSelectPromise; let selectPromise = new Promise((resolve) => { @@ -926,6 +926,7 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature { this._removedByStartupPage = true; gBrowser.removeTab(this._tabToRemoveForEmpty, { skipSessionStore: true, + animate: false, }); cleanup(); }, 0);