From 2a33ecf02af825776f88010ca9ed5397fba93fdb Mon Sep 17 00:00:00 2001 From: Alex Kontos Date: Tue, 5 Aug 2025 13:34:42 +0100 Subject: [PATCH] refactor: tab features * support for `browser.newtab.url` --- waterfox/browser/components/WaterfoxGlue.jsm | 2 +- .../components/tabfeatures/TabFeatures.jsm | 156 --------- .../tabfeatures/TabFeatures.sys.mjs | 322 ++++++++++++++++++ .../tabfeatures/content/pinnedtab.css | 5 +- .../tabfeatures/content/tabfeatures.xhtml | 31 +- .../browser/components/tabfeatures/moz.build | 2 +- .../test/browser/browser_tabfeatures.js | 28 +- .../tabfeatures/test/browser/head.js | 48 ++- 8 files changed, 375 insertions(+), 219 deletions(-) delete mode 100644 waterfox/browser/components/tabfeatures/TabFeatures.jsm create mode 100644 waterfox/browser/components/tabfeatures/TabFeatures.sys.mjs diff --git a/waterfox/browser/components/WaterfoxGlue.jsm b/waterfox/browser/components/WaterfoxGlue.jsm index 3b24743a19a2..b7be572bca78 100644 --- a/waterfox/browser/components/WaterfoxGlue.jsm +++ b/waterfox/browser/components/WaterfoxGlue.jsm @@ -22,7 +22,7 @@ XPCOMUtils.defineLazyModuleGetters(lazy, { PrefUtils: "resource:///modules/PrefUtils.jsm", PrivateTab: "resource:///modules/PrivateTab.sys.mjs", StatusBar: "resource:///modules/StatusBar.sys.mjs", - TabFeatures: "resource:///modules/TabFeatures.jsm", + TabFeatures: "resource:///modules/TabFeatures.sys.mjs", UICustomizations: "resource:///modules/UICustomizations.jsm", }); diff --git a/waterfox/browser/components/tabfeatures/TabFeatures.jsm b/waterfox/browser/components/tabfeatures/TabFeatures.jsm deleted file mode 100644 index 81dd51dd46bd..000000000000 --- a/waterfox/browser/components/tabfeatures/TabFeatures.jsm +++ /dev/null @@ -1,156 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global */ - -const EXPORTED_SYMBOLS = ["TabFeatures"]; - -const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); - -const { AppConstants } = ChromeUtils.import( - "resource://gre/modules/AppConstants.jsm" -); - -const TabFeatures = { - PREF_ACTIVETAB: "browser.tabs.copyurl.activetab", - PREF_REQUIRECONFIRM: "browser.restart_menu.requireconfirm", - PREF_PURGECACHE: "browser.restart_menu.purgecache", - - init(window) { - window.TabFeatures = this; - this.initListeners(window); - }, - - initListeners(aWindow) { - aWindow.document - .getElementById("tabContextMenu") - ?.addEventListener("popupshowing", this.tabContext); - if (AppConstants.platform == "macosx") { - aWindow.document - .getElementById("file-menu") - ?.addEventListener("popupshowing", this.tabContext); - } else { - aWindow.document - .getElementById("appMenu-popup") - ?.addEventListener("popupshowing", this.tabContext); - } - }, - - tabContext(aEvent) { - let win = aEvent.view; - if (!win) { - win = Services.wm.getMostRecentWindow("navigator:browser"); - } - let { document } = win; - let elements = document.getElementsByClassName("tabFeature"); - for (let i = 0; i < elements.length; i++) { - let el = elements[i]; - let pref = el.getAttribute("preference"); - if (pref) { - let visible = Services.prefs.getBoolPref(pref); - el.hidden = !visible; - } - } - // Can't unload selected tab, so don't show menu item in that case - if (win.TabContextMenu.contextTab === win.gBrowser.selectedTab) { - const el = document.getElementById("context_unloadTab"); - el.hidden = true; - } - }, - - // Copies current tab url to clipboard - copyTabUrl(aUri, aWindow) { - const gClipboardHelper = Cc[ - "@mozilla.org/widget/clipboardhelper;1" - ].getService(Ci.nsIClipboardHelper); - try { - Services.prefs.getBoolPref(this.PREF_ACTIVETAB) - ? gClipboardHelper.copyString(aWindow.gBrowser.currentURI.spec) - : gClipboardHelper.copyString(aUri); - } catch (e) { - throw new Error( - "We're sorry but something has gone wrong with 'CopyTabUrl' " + e - ); - } - }, - - // Copies all tab urls to clipboard - copyAllTabUrls(aWindow) { - const gClipboardHelper = Cc[ - "@mozilla.org/widget/clipboardhelper;1" - ].getService(Ci.nsIClipboardHelper); - //Get all urls - let urlArr = this._getAllUrls(aWindow); - try { - // Enumerate all urls in to a list. - let urlList = urlArr.join("\n"); - // Send list to clipboard. - gClipboardHelper.copyString(urlList.trim()); - // Clear url list after clipboard event - urlList = ""; - } catch (e) { - throw new Error( - "We're sorry but something has gone wrong with 'copyAllTabUrls' " + e - ); - } - }, - - // Get all the tab urls into an array. - _getAllUrls(aWindow) { - // We don't want to copy about uri's - let blocklist = /^about:.*/i; - let urlArr = []; - let tabCount = aWindow.gBrowser.browsers.length; - Array(tabCount) - .fill() - .map((_, i) => { - let spec = aWindow.gBrowser.getBrowserAtIndex(i).currentURI.spec; - if (!blocklist.test(spec)) { - urlArr.push(spec); - } - }); - return urlArr; - }, - - async restartBrowser() { - try { - if (Services.prefs.getBoolPref(this.PREF_REQUIRECONFIRM)) { - // Need brand in here to be able to expand { -brand-short-name } - let l10n = new Localization([ - "branding/brand.ftl", - "browser/waterfox.ftl", - ]); - let [title, question] = ( - await l10n.formatMessages([ - { id: "restart-prompt-title" }, - { id: "restart-prompt-question" }, - ]) - ).map(({ value }) => value); - - if (Services.prompt.confirm(null, title, question)) { - // only restart if confirmation given - this._attemptRestart(); - } - } else { - this._attemptRestart(); - } - } catch (e) { - Cu.reportError( - "We're sorry but something has gone wrong with 'restartBrowser' " + e - ); - } - }, - - _attemptRestart() { - // Purge cache if required - if (Services.prefs.getBoolPref(this.PREF_PURGECACHE)) { - Services.appinfo.invalidateCachesOnRestart(); - } - - // Initiate the restart - Services.startup.quit( - Services.startup.eRestart | Services.startup.eAttemptQuit - ); - }, -}; diff --git a/waterfox/browser/components/tabfeatures/TabFeatures.sys.mjs b/waterfox/browser/components/tabfeatures/TabFeatures.sys.mjs new file mode 100644 index 000000000000..6e55cfa84fd1 --- /dev/null +++ b/waterfox/browser/components/tabfeatures/TabFeatures.sys.mjs @@ -0,0 +1,322 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs", + setTimeout: "resource://gre/modules/Timer.sys.mjs", +}); + +export const TabFeatures = { + NEW_TAB_CONFIG_PATH: "browser.newtab.url", + newTabURL: null, + prefListener: null, + PREF_ACTIVETAB: "browser.tabs.copyurl.activetab", + PREF_REQUIRECONFIRM: "browser.restart_menu.requireconfirm", + PREF_PURGECACHE: "browser.restart_menu.purgecache", + + init(aWindow) { + // Wait for XUL elements to be available before initializing listeners. + // 'context_copyTabUrl' is an element from our associated XUL, which we will now wait for. + if (!aWindow.document.getElementById("context_copyTabUrl")) { + lazy.setTimeout(() => { + this.init(aWindow); + }, 50); // Retry after 50ms + return; + } + + aWindow.TabFeatures = this; + this.initListeners(aWindow); + this.initNewTabConfig(); // Does not require aWindow + this.initNewTabFocus(aWindow); + }, + + destroy() { + this.destroyNewTabConfig(); + }, + + initListeners(aWindow) { + const doc = aWindow.document; + + doc + .getElementById("tabContextMenu") + ?.addEventListener("popupshowing", this.tabContext.bind(this)); + if (AppConstants.platform === "macosx") { + doc + .getElementById("file-menu") + ?.addEventListener("popupshowing", this.tabContext.bind(this)); + } else { + doc + .getElementById("appMenu-popup") + ?.addEventListener("popupshowing", this.tabContext.bind(this)); + } + + const copyTabUrlElement = doc.getElementById("context_copyTabUrl"); + if (copyTabUrlElement) { + copyTabUrlElement.addEventListener("command", (_event) => { + if (aWindow.TabContextMenu?.contextTab?.linkedBrowser) { + try { + this.copyTabUrl( + aWindow.TabContextMenu.contextTab.linkedBrowser.currentURI.spec, + aWindow + ); + } catch (e) { + console.error( + "TabFeatures: Error inside copyTabUrl listener execution:", + e + ); + } + } else { + // console.warn("TabFeatures: copyTabUrl not called, context or linkedBrowser not available."); + } + }); + } else { + console.error( + "TabFeatures: FAILED to find element 'context_copyTabUrl'. Listener NOT attached." + ); + } + + doc + .getElementById("context_copyAllTabUrls") + ?.addEventListener("command", (_event) => { + this.copyAllTabUrls(aWindow); + }); + + doc + .getElementById("context_unloadTab") + ?.addEventListener("command", (_event) => { + if ( + aWindow.gBrowser && + aWindow.TabContextMenu && + aWindow.TabContextMenu.contextTab + ) { + // Prevent unloading if it's the last tab or the only non-pinned tab in the window + if ( + aWindow.gBrowser.tabs.length > 1 && + (Array.from(aWindow.gBrowser.tabs).filter((t) => !t.pinned).length > + 1 || + !aWindow.TabContextMenu.contextTab.pinned) + ) { + aWindow.gBrowser.discardBrowser(aWindow.TabContextMenu.contextTab); + } else { + // console.log("TabFeatures: discardBrowser not called, conditions not met (e.g., last tab)."); + } + } else { + // console.warn("TabFeatures: discardBrowser not called, context not available."); + } + }); + + const restartMac = doc.getElementById("app_restartBrowser"); + if (restartMac) { + restartMac.addEventListener("command", (_event) => { + this.restartBrowser(); + }); + } + + const restartOther = doc.getElementById("appMenu-restart-button"); + if (restartOther && restartOther.getAttribute("data-tabfeatures-handler-attached") !== "true") { + restartOther.addEventListener("command", (_event) => { + this.restartBrowser(); + }); + restartOther.setAttribute("data-tabfeatures-handler-attached", "true"); + } + }, + + initNewTabConfig() { + // Fetch pref if it exists + this.newTabURL = Services.prefs.getStringPref(this.NEW_TAB_CONFIG_PATH, ""); + + // Only proceed if a value is actually set + if (this.newTabURL) { + try { + lazy.AboutNewTab.newTabURL = this.newTabURL; + this.prefListener = Services.prefs.addObserver( + this.NEW_TAB_CONFIG_PATH, + (_subject, _topic, _data) => { + const newURL = Services.prefs.getStringPref( + this.NEW_TAB_CONFIG_PATH, + "" + ); + if (newURL) { + lazy.AboutNewTab.newTabURL = newURL; + } else { + // If the pref is cleared, revert to default behavior + lazy.AboutNewTab.resetNewTabURL(); + } + } + ); + } catch (e) { + console.error("Error initializing new tab config:", e); + } + } + }, + + initNewTabFocus(window) { + window.gBrowser.tabContainer.addEventListener("TabOpen", (event) => { + const tab = event.target; + const browser = window.gBrowser.getBrowserForTab(tab); + + browser.addEventListener( + "load", + function onLoad() { + browser.removeEventListener("load", onLoad); + window.setTimeout(() => { + browser.contentWindow.focus(); + }, 0); + }, + { once: true } + ); + }); + }, + + destroyNewTabConfig() { + if (this.prefListener) { + Services.prefs.removeObserver( + this.NEW_TAB_CONFIG_PATH, + this.prefListener + ); + this.prefListener = null; + } + }, + + tabContext(aEvent) { + let win = aEvent.view; + if (!win) { + win = Services.wm.getMostRecentWindow("navigator:browser"); + } + const { document } = win; + const elements = document.getElementsByClassName("tabFeature"); + for (let i = 0; i < elements.length; i++) { + const el = elements[i]; + const pref = el.getAttribute("preference"); + if (pref) { + const visible = Services.prefs.getBoolPref(pref); + el.hidden = !visible; + } + } + // Can't unload selected tab, so don't show menu item in that case + if (win.TabContextMenu.contextTab === win.gBrowser.selectedTab) { + const el = document.getElementById("context_unloadTab"); + el.hidden = true; + } + + // Ensure restart button in App Menu (Windows/Linux) has its handler after template instantiation + const restartBtn = document.getElementById("appMenu-restart-button"); + if (restartBtn) { + // Toggle iconic styling to match icon prefs so alignment matches Exit when icons are disabled + const iconsDisabled = Services.prefs.getBoolPref("userChrome.icon.disabled", false); + const iconsInPanel = Services.prefs.getBoolPref("userChrome.icon.panel", false); + const shouldIconic = iconsInPanel && !iconsDisabled; + restartBtn.classList.toggle("subviewbutton-iconic", shouldIconic); + + if (restartBtn.getAttribute("data-tabfeatures-handler-attached") !== "true") { + restartBtn.addEventListener("command", (_event) => { + this.restartBrowser(); + }); + restartBtn.setAttribute("data-tabfeatures-handler-attached", "true"); + } + } + }, + + // Copies current tab url to clipboard + copyTabUrl(aUri, aWindow) { + const gClipboardHelper = Cc[ + "@mozilla.org/widget/clipboardhelper;1" + ].getService(Ci.nsIClipboardHelper); + try { + Services.prefs.getBoolPref(this.PREF_ACTIVETAB) + ? gClipboardHelper.copyString(aWindow.gBrowser.currentURI.spec) + : gClipboardHelper.copyString(aUri); + } catch (e) { + throw new Error( + `We're sorry but something has gone wrong with 'CopyTabUrl' ${e}` + ); + } + }, + + // Copies all tab urls to clipboard + copyAllTabUrls(aWindow) { + const gClipboardHelper = Cc[ + "@mozilla.org/widget/clipboardhelper;1" + ].getService(Ci.nsIClipboardHelper); + //Get all urls + const urlArr = this._getAllUrls(aWindow); + try { + // Enumerate all urls in to a list. + let urlList = urlArr.join("\n"); + // Send list to clipboard. + gClipboardHelper.copyString(urlList.trim()); + // Clear url list after clipboard event + urlList = ""; + } catch (e) { + throw new Error( + `We're sorry but something has gone wrong with 'copyAllTabUrls' ${e}` + ); + } + }, + + // Get all the tab urls into an array. + _getAllUrls(aWindow) { + // We don't want to copy about uri's + const blocklist = /^about:.*/i; + const urlArr = []; + const tabCount = aWindow.gBrowser.browsers.length; + Array(tabCount) + .fill() + .map((_, i) => { + const spec = aWindow.gBrowser.getBrowserAtIndex(i).currentURI.spec; + if (!blocklist.test(spec)) { + urlArr.push(spec); + } + }); + return urlArr; + }, + + async restartBrowser() { + try { + if (Services.prefs.getBoolPref(this.PREF_REQUIRECONFIRM)) { + // Need brand in here to be able to expand { -brand-short-name } + const l10n = new Localization([ + "branding/brand.ftl", + "browser/waterfox.ftl", + ]); + const [title, question] = ( + await l10n.formatMessages([ + { id: "restart-prompt-title" }, + { id: "restart-prompt-question" }, + ]) + ).map(({ value }) => value); + + if (Services.prompt.confirm(null, title, question)) { + // only restart if confirmation given + this._attemptRestart(); + } + } else { + this._attemptRestart(); + } + } catch (e) { + console.error( + "We're sorry but something has gone wrong with 'restartBrowser' ", + e + ); + } + }, + + _attemptRestart() { + // Purge cache if required + if (Services.prefs.getBoolPref(this.PREF_PURGECACHE)) { + Services.appinfo.invalidateCachesOnRestart(); + } + + // Initiate the restart + Services.startup.quit( + Services.startup.eRestart | Services.startup.eAttemptQuit + ); + }, +}; diff --git a/waterfox/browser/components/tabfeatures/content/pinnedtab.css b/waterfox/browser/components/tabfeatures/content/pinnedtab.css index 39f25ccad9a9..80a7d8ca7d9b 100644 --- a/waterfox/browser/components/tabfeatures/content/pinnedtab.css +++ b/waterfox/browser/components/tabfeatures/content/pinnedtab.css @@ -4,8 +4,9 @@ max-width: 225px; min-width: var(--tab-min-width); width: 0; - transition: min-width 100ms ease-out, - max-width 100ms ease-out; + transition: + min-width 100ms ease-out, + max-width 100ms ease-out; } .tabbrowser-tab:is([pinned]):not([fadein]) { diff --git a/waterfox/browser/components/tabfeatures/content/tabfeatures.xhtml b/waterfox/browser/components/tabfeatures/content/tabfeatures.xhtml index 0a10d0fe3654..a5878d2aeb0e 100644 --- a/waterfox/browser/components/tabfeatures/content/tabfeatures.xhtml +++ b/waterfox/browser/components/tabfeatures/content/tabfeatures.xhtml @@ -8,35 +8,32 @@ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - - + #ifdef XP_MACOSX - #else - - - - - - + + + + + + #endif diff --git a/waterfox/browser/components/tabfeatures/moz.build b/waterfox/browser/components/tabfeatures/moz.build index 7d8bc9e33233..0d421f29e454 100644 --- a/waterfox/browser/components/tabfeatures/moz.build +++ b/waterfox/browser/components/tabfeatures/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXTRA_JS_MODULES += [ - "TabFeatures.jsm", + "TabFeatures.sys.mjs", ] BROWSER_CHROME_MANIFESTS += ["test/browser/browser.ini"] diff --git a/waterfox/browser/components/tabfeatures/test/browser/browser_tabfeatures.js b/waterfox/browser/components/tabfeatures/test/browser/browser_tabfeatures.js index ef524e729fd0..f86ba098bf83 100644 --- a/waterfox/browser/components/tabfeatures/test/browser/browser_tabfeatures.js +++ b/waterfox/browser/components/tabfeatures/test/browser/browser_tabfeatures.js @@ -1,9 +1,7 @@ -"use strict"; - add_task(async function testCopyTabUrls() { // Make sure elements are present - let copyTabUrl = document.getElementById("context_copyTabUrl"); - let copyAllTabUrls = document.getElementById("context_copyAllTabUrls"); + const copyTabUrl = document.getElementById("context_copyTabUrl"); + const copyAllTabUrls = document.getElementById("context_copyAllTabUrls"); ok(copyTabUrl, "Copy tab URL is included"); ok(copyAllTabUrls, "Copy all tab URLs is included"); // Make sure that defaults are set correctly @@ -27,7 +25,7 @@ add_task(async function testCopyTabUrls() { add_task(async function testHideDuplicateTab() { // Setting duplicateTab pref to false should hide element in all windows - let duplicateTab = document.getElementById("context_duplicateTab"); + const duplicateTab = document.getElementById("context_duplicateTab"); Services.prefs.setBoolPref(DUPLICATE_TAB_PREF, false); await openAndCloseTabContextMenu(gBrowser.selectedTab); is(duplicateTab.hidden, true, "Duplicate tab hidden"); @@ -40,13 +38,13 @@ add_task(async function testHideDuplicateTab() { add_task(async function testRestartItem() { // Make sure element is present - let restartBrowserMenu = document.getElementById("app_restartBrowser"); + const restartBrowserMenu = document.getElementById("app_restartBrowser"); // Need to use PanelMultiView to get PanelUI elements - let restartBrowserApp = PanelMultiView.getViewNode( + const restartBrowserApp = PanelMultiView.getViewNode( document, "appMenu-restart-button" ); - if (OS == "macosx") { + if (OS === "macosx") { ok(restartBrowserMenu, "Restart browser menu bar item is included"); is(restartBrowserApp, null, "Restart browser appMenu item not included"); await openAndCloseFileMenu(); @@ -65,7 +63,7 @@ add_task(async function testRestartItem() { } // Make sure element is hidden Services.prefs.setBoolPref(RESTART_PREF, false); - if (OS == "macosx") { + if (OS === "macosx") { await openAndCloseFileMenu(); is( restartBrowserMenu.hidden, @@ -77,22 +75,22 @@ add_task(async function testRestartItem() { }); add_task(async function testCopyUrlFunctionality() { - let copyTabUrl = document.getElementById("context_copyTabUrl"); - let copyAllTabUrls = document.getElementById("context_copyAllTabUrls"); + const copyTabUrl = document.getElementById("context_copyTabUrl"); + const copyAllTabUrls = document.getElementById("context_copyAllTabUrls"); const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URI1); - let browser = tab.linkedBrowser; + const browser = tab.linkedBrowser; // Test copy tab url copies URL await openTabContextMenu(tab); EventUtils.synthesizeMouseAtCenter(copyTabUrl, {}); - let tabURI = await pasteFromClipboard(browser); + const tabURI = await pasteFromClipboard(browser); is(tabURI, URI1); // Test copy all tab urls Services.prefs.setBoolPref(COPY_ALL_URLS_PREF, true); const tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, URI2); await openTabContextMenu(tab); EventUtils.synthesizeMouseAtCenter(copyAllTabUrls, {}); - let tabURIs = await pasteFromClipboard(browser); - is(tabURIs, URI1 + "\n" + URI2); + const tabURIs = await pasteFromClipboard(browser); + is(tabURIs, `${URI1}\n${URI2}`); // Test copy active tab pref Services.prefs.setBoolPref(COPY_ACTIVE_URL_PREF, true); await openTabContextMenu(tab); diff --git a/waterfox/browser/components/tabfeatures/test/browser/head.js b/waterfox/browser/components/tabfeatures/test/browser/head.js index 1b41a70509bc..6d261b7413b0 100644 --- a/waterfox/browser/components/tabfeatures/test/browser/head.js +++ b/waterfox/browser/components/tabfeatures/test/browser/head.js @@ -1,28 +1,22 @@ -"use strict"; +const { synthesizeDrop, synthesizeMouseAtCenter } = EventUtils; -const { AppConstants } = ChromeUtils.import( - "resource://gre/modules/AppConstants.jsm" -); +const _COPY_URL_PREF = "browser.tabs.copyurl"; +const _COPY_ALL_URLS_PREF = "browser.tabs.copyallurls"; +const _COPY_ACTIVE_URL_PREF = "browser.tabs.copyurl.activetab"; +const _DUPLICATE_TAB_PREF = "browser.tabs.duplicateTab"; +const _RESTART_PREF = "browser.restart_menu.showpanelmenubtn"; -var { synthesizeDrop, synthesizeMouseAtCenter } = EventUtils; +const _URI1 = "https://test1.example.com/"; +const _URI2 = "https://example.com/"; -const COPY_URL_PREF = "browser.tabs.copyurl"; -const COPY_ALL_URLS_PREF = "browser.tabs.copyallurls"; -const COPY_ACTIVE_URL_PREF = "browser.tabs.copyurl.activetab"; -const DUPLICATE_TAB_PREF = "browser.tabs.duplicateTab"; -const RESTART_PREF = "browser.restart_menu.showpanelmenubtn"; - -const URI1 = "https://test1.example.com/"; -const URI2 = "https://example.com/"; - -let OS = AppConstants.platform; +const _OS = AppConstants.platform; /** * Helper for opening the toolbar context menu. */ async function openTabContextMenu(tab) { info("Opening tab context menu"); - let contextMenu = document.getElementById("tabContextMenu"); - let openTabContextMenuPromise = BrowserTestUtils.waitForPopupEvent( + const contextMenu = document.getElementById("tabContextMenu"); + const openTabContextMenuPromise = BrowserTestUtils.waitForPopupEvent( contextMenu, "shown" ); @@ -32,7 +26,7 @@ async function openTabContextMenu(tab) { return contextMenu; } -async function openAndCloseTabContextMenu(tab) { +async function _openAndCloseTabContextMenu(tab) { await openTabContextMenu(tab); info("Opened tab context menu"); await EventUtils.synthesizeKey("VK_ESCAPE", {}); @@ -44,8 +38,8 @@ async function openAndCloseTabContextMenu(tab) { */ async function openFileMenu() { info("Opening file menu"); - let fileMenu = document.getElementById("file-menu"); - let openFileMenuPromise = BrowserTestUtils.waitForPopupEvent( + const fileMenu = document.getElementById("file-menu"); + const openFileMenuPromise = BrowserTestUtils.waitForPopupEvent( fileMenu, "shown" ); @@ -54,7 +48,7 @@ async function openFileMenu() { return fileMenu; } -async function openAndCloseFileMenu() { +async function _openAndCloseFileMenu() { await openFileMenu(); await EventUtils.synthesizeKey("VK_ESCAPE", {}); info("Closed file menu"); @@ -63,8 +57,8 @@ async function openAndCloseFileMenu() { /** * Helper for opening toolbar context menu. */ -async function openToolbarContextMenu(contextMenu, target) { - let popupshown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); +async function _openToolbarContextMenu(contextMenu, target) { + const popupshown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); EventUtils.synthesizeMouseAtCenter(target, { type: "contextmenu" }); await popupshown; } @@ -73,15 +67,15 @@ async function openToolbarContextMenu(contextMenu, target) { * Helper to paste from clipboard */ -async function pasteFromClipboard(browser) { +async function _pasteFromClipboard(browser) { return SpecialPowers.spawn(browser, [], () => { - let { document } = content; + const { document } = content; document.body.contentEditable = true; document.body.focus(); - let pastePromise = new Promise(resolve => { + const pastePromise = new Promise((resolve) => { document.addEventListener( "paste", - e => { + (e) => { resolve(e.clipboardData.getData("text/plain")); }, { once: true }