feat: add TabFeatures implemented with overlays
(cherry picked from commit 09d6df4188732749da7648ec58bf22c1dd0c7949)
This commit is contained in:
@@ -238,3 +238,13 @@ pref("userContent.page.proton", true); // Need proton_color
|
|||||||
// ** Useful Options ***********************************************************
|
// ** Useful Options ***********************************************************
|
||||||
// Integrated calculator at urlbar
|
// Integrated calculator at urlbar
|
||||||
pref("browser.urlbar.suggest.calculator", true);
|
pref("browser.urlbar.suggest.calculator", true);
|
||||||
|
|
||||||
|
// Extensibles prefs
|
||||||
|
pref("browser.tabs.duplicateTab", true);
|
||||||
|
pref("browser.tabs.copyurl", true);
|
||||||
|
pref("browser.tabs.copyallurls", false);
|
||||||
|
pref("browser.tabs.copyurl.activetab", false);
|
||||||
|
pref("browser.tabs.unloadTab", false);
|
||||||
|
pref("browser.restart_menu.showpanelmenubtn", true);
|
||||||
|
pref("browser.restart_menu.purgecache", false);
|
||||||
|
pref("browser.restart_menu.requireconfirm", true);
|
||||||
@@ -15,6 +15,7 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
ChromeManifest: "resource:///modules/ChromeManifest.jsm",
|
ChromeManifest: "resource:///modules/ChromeManifest.jsm",
|
||||||
Overlays: "resource:///modules/Overlays.jsm",
|
Overlays: "resource:///modules/Overlays.jsm",
|
||||||
|
TabFeatures: "resource:///modules/TabFeatures.jsm",
|
||||||
});
|
});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||||
@@ -60,6 +61,8 @@ const WaterfoxGlue = {
|
|||||||
if (subject.URL.includes("browser.xhtml")) {
|
if (subject.URL.includes("browser.xhtml")) {
|
||||||
const window = subject.defaultView;
|
const window = subject.defaultView;
|
||||||
Overlays.load(this.startupManifest, window);
|
Overlays.load(this.startupManifest, window);
|
||||||
|
|
||||||
|
TabFeatures.init(window);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
overlay chrome://browser/content/browser.xhtml chrome://browser/content/overlays/tabfeatures.xhtml
|
||||||
@@ -4,6 +4,10 @@
|
|||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
DIRS += [
|
||||||
|
"tabfeatures",
|
||||||
|
]
|
||||||
|
|
||||||
EXTRA_JS_MODULES += [
|
EXTRA_JS_MODULES += [
|
||||||
"WaterfoxGlue.jsm",
|
"WaterfoxGlue.jsm",
|
||||||
]
|
]
|
||||||
|
|||||||
167
waterfox/browser/components/tabfeatures/TabFeatures.jsm
Normal file
167
waterfox/browser/components/tabfeatures/TabFeatures.jsm
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/* 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",
|
||||||
|
|
||||||
|
get browserBundle() {
|
||||||
|
return Services.strings.createBundle(
|
||||||
|
"chrome://extensibles/locale/extensibles.properties"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
get brandBundle() {
|
||||||
|
return Services.strings.createBundle(
|
||||||
|
"chrome://branding/locale/brand.properties"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
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/extensibles.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
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<!-- 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/. -->
|
||||||
|
|
||||||
|
#filter substitution
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<overlay id="tabfeature-overlay" xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<popupset id="mainPopupSet">
|
||||||
|
<menupopup id="tabContextMenu">
|
||||||
|
<menuitem id="context_duplicateTab" data-lazy-l10n-id="duplicate-tab"
|
||||||
|
oncommand="duplicateTabIn(TabContextMenu.contextTab, 'tab');" class="tabFeature"
|
||||||
|
preference="browser.tabs.duplicateTab" />
|
||||||
|
<menuitem id="context_copyTabUrl" class="tabFeature"
|
||||||
|
oncommand="TabFeatures.copyTabUrl(TabContextMenu.contextTab.linkedBrowser.currentURI.spec, window);"
|
||||||
|
data-lazy-l10n-id="copy-url" preference="browser.tabs.copyurl" insertafter="context_duplicateTab" />
|
||||||
|
<menuitem id="context_copyAllTabUrls" class="tabFeature" oncommand="TabFeatures.copyAllTabUrls(window);"
|
||||||
|
data-lazy-l10n-id="copy-all-urls" preference="browser.tabs.copyallurls"
|
||||||
|
insertafter="context_copyTabUrl" />
|
||||||
|
<menuitem id="context_unloadTab" class="tabFeature"
|
||||||
|
oncommand="gBrowser.discardBrowser(TabContextMenu.contextTab);" data-lazy-l10n-id="unload-tab"
|
||||||
|
preference="browser.tabs.unloadTab" insertafter="context_copyAllTabUrls" />
|
||||||
|
</menupopup>
|
||||||
|
</popupset>
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
<menubar id="main-menubar">
|
||||||
|
<menuitem id="app_restartBrowser" class="tabFeature" oncommand="TabFeatures.restartBrowser();"
|
||||||
|
data-l10n-id="appmenuitem-restart-browser" preference="browser.restart_menu.showpanelmenubtn" hidden="true"
|
||||||
|
insertafter="goOfflineMenuitem" />
|
||||||
|
</menubar>
|
||||||
|
#else
|
||||||
|
<html:template id="appMenu-viewCache">
|
||||||
|
<panelview id="appMenu-protonMainView">
|
||||||
|
<vbox id="appMenu-subview-body" class="panel-subview-body">
|
||||||
|
<toolbarbutton id="appMenu-restart-button" class="subviewbutton subviewbutton-iconic tabFeature"
|
||||||
|
oncommand="TabFeatures.restartBrowser();" data-l10n-id="appmenuitem-restart-browser"
|
||||||
|
preference="browser.restart_menu.showpanelmenubtn" hidden="true" />
|
||||||
|
</vbox>
|
||||||
|
</panelview>
|
||||||
|
</html:template>
|
||||||
|
#endif
|
||||||
|
</overlay>
|
||||||
3
waterfox/browser/components/tabfeatures/jar.mn
Normal file
3
waterfox/browser/components/tabfeatures/jar.mn
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
browser.jar:
|
||||||
|
% content browser %content/browser/ contentaccessible=yes
|
||||||
|
* content/browser/overlays/tabfeatures.xhtml (content/tabfeatures.xhtml)
|
||||||
13
waterfox/browser/components/tabfeatures/moz.build
Normal file
13
waterfox/browser/components/tabfeatures/moz.build
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
EXTRA_JS_MODULES += [
|
||||||
|
"TabFeatures.jsm",
|
||||||
|
]
|
||||||
|
|
||||||
|
BROWSER_CHROME_MANIFESTS += ["test/browser/browser.ini"]
|
||||||
|
|
||||||
|
JAR_MANIFESTS += ["jar.mn"]
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
tags = waterfox_tabfeatures
|
||||||
|
firefox-appdir = browser
|
||||||
|
support-files =
|
||||||
|
head.js
|
||||||
|
|
||||||
|
[browser_tabfeatures.js]
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
add_task(async function testCopyTabUrls() {
|
||||||
|
// Make sure elements are present
|
||||||
|
let copyTabUrl = document.getElementById("context_copyTabUrl");
|
||||||
|
let 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
|
||||||
|
await openAndCloseTabContextMenu(gBrowser.selectedTab);
|
||||||
|
is(copyTabUrl.hidden, false, "Copy tab URL visible by default");
|
||||||
|
is(copyAllTabUrls.hidden, true, "Copy all tab URLs hidden by default");
|
||||||
|
// Make sure changing prefs causes elements to be shown/hidden
|
||||||
|
Services.prefs.setBoolPref(COPY_URL_PREF, false);
|
||||||
|
Services.prefs.setBoolPref(COPY_ALL_URLS_PREF, false);
|
||||||
|
await openAndCloseTabContextMenu(gBrowser.selectedTab);
|
||||||
|
is(copyTabUrl.hidden, true, "Copy tab URL hidden");
|
||||||
|
is(copyAllTabUrls.hidden, true, "Copy all tab URLs hidden");
|
||||||
|
Services.prefs.setBoolPref(COPY_URL_PREF, true);
|
||||||
|
Services.prefs.setBoolPref(COPY_ALL_URLS_PREF, true);
|
||||||
|
await openAndCloseTabContextMenu(gBrowser.selectedTab);
|
||||||
|
is(copyTabUrl.hidden, false, "Copy tab URL visible");
|
||||||
|
is(copyAllTabUrls.hidden, false, "Copy all tab URLs visible");
|
||||||
|
Services.prefs.clearUserPref(COPY_URL_PREF);
|
||||||
|
Services.prefs.clearUserPref(COPY_ALL_URLS_PREF);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testHideDuplicateTab() {
|
||||||
|
// Setting duplicateTab pref to false should hide element in all windows
|
||||||
|
let duplicateTab = document.getElementById("context_duplicateTab");
|
||||||
|
Services.prefs.setBoolPref(DUPLICATE_TAB_PREF, false);
|
||||||
|
await openAndCloseTabContextMenu(gBrowser.selectedTab);
|
||||||
|
is(duplicateTab.hidden, true, "Duplicate tab hidden");
|
||||||
|
// Should fall back to default value of true, i.e. element showing
|
||||||
|
Services.prefs.clearUserPref(DUPLICATE_TAB_PREF);
|
||||||
|
// Ensure showing
|
||||||
|
await openAndCloseTabContextMenu(gBrowser.selectedTab);
|
||||||
|
is(duplicateTab.hidden, false, "Duplicate tab showing");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testRestartItem() {
|
||||||
|
// Make sure element is present
|
||||||
|
let restartBrowserMenu = document.getElementById("app_restartBrowser");
|
||||||
|
// Need to use PanelMultiView to get PanelUI elements
|
||||||
|
let restartBrowserApp = PanelMultiView.getViewNode(
|
||||||
|
document,
|
||||||
|
"appMenu-restart-button"
|
||||||
|
);
|
||||||
|
if (OS == "macosx") {
|
||||||
|
ok(restartBrowserMenu, "Restart browser menu bar item is included");
|
||||||
|
is(restartBrowserApp, null, "Restart browser appMenu item not included");
|
||||||
|
await openAndCloseFileMenu();
|
||||||
|
is(
|
||||||
|
restartBrowserMenu.hidden,
|
||||||
|
false,
|
||||||
|
"Restart browser menu bar item is visible"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
is(
|
||||||
|
restartBrowserMenu,
|
||||||
|
null,
|
||||||
|
"Restart browser menu bar item is not included"
|
||||||
|
);
|
||||||
|
ok(restartBrowserApp, "Restart browser appMenu item included");
|
||||||
|
}
|
||||||
|
// Make sure element is hidden
|
||||||
|
Services.prefs.setBoolPref(RESTART_PREF, false);
|
||||||
|
if (OS == "macosx") {
|
||||||
|
await openAndCloseFileMenu();
|
||||||
|
is(
|
||||||
|
restartBrowserMenu.hidden,
|
||||||
|
true,
|
||||||
|
"Restart browser menu bar item is hidden"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Services.prefs.clearUserPref(RESTART_PREF);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testCopyUrlFunctionality() {
|
||||||
|
let copyTabUrl = document.getElementById("context_copyTabUrl");
|
||||||
|
let copyAllTabUrls = document.getElementById("context_copyAllTabUrls");
|
||||||
|
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URI1);
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
// Test copy tab url copies URL
|
||||||
|
await openTabContextMenu(tab);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(copyTabUrl, {});
|
||||||
|
let 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);
|
||||||
|
// Test copy active tab pref
|
||||||
|
Services.prefs.setBoolPref(COPY_ACTIVE_URL_PREF, true);
|
||||||
|
await openTabContextMenu(tab);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(copyTabUrl, {});
|
||||||
|
let activeURI = await pasteFromClipboard(browser);
|
||||||
|
// URI2 should be active, so we copy from tab1 to verify
|
||||||
|
is(activeURI, URI2);
|
||||||
|
// Then we verify that URI1 is copied when active pref is false
|
||||||
|
Services.prefs.setBoolPref(COPY_ACTIVE_URL_PREF, false);
|
||||||
|
await openTabContextMenu(tab);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(copyTabUrl, {});
|
||||||
|
activeURI = await pasteFromClipboard(browser);
|
||||||
|
is(activeURI, URI1);
|
||||||
|
// Cleanup
|
||||||
|
Services.prefs.clearUserPref(COPY_ALL_URLS_PREF);
|
||||||
|
Services.prefs.clearUserPref(COPY_ACTIVE_URL_PREF);
|
||||||
|
BrowserTestUtils.removeTab(tab);
|
||||||
|
BrowserTestUtils.removeTab(tab2);
|
||||||
|
});
|
||||||
93
waterfox/browser/components/tabfeatures/test/browser/head.js
Normal file
93
waterfox/browser/components/tabfeatures/test/browser/head.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { AppConstants } = ChromeUtils.import(
|
||||||
|
"resource://gre/modules/AppConstants.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
|
var { synthesizeDrop, synthesizeMouseAtCenter } = EventUtils;
|
||||||
|
|
||||||
|
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;
|
||||||
|
/**
|
||||||
|
* 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(
|
||||||
|
contextMenu,
|
||||||
|
"shown"
|
||||||
|
);
|
||||||
|
|
||||||
|
EventUtils.synthesizeMouseAtCenter(tab, { type: "contextmenu" });
|
||||||
|
await openTabContextMenuPromise;
|
||||||
|
return contextMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openAndCloseTabContextMenu(tab) {
|
||||||
|
await openTabContextMenu(tab);
|
||||||
|
info("Opened tab context menu");
|
||||||
|
await EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||||
|
info("Closed tab context menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for opening the file menu.
|
||||||
|
*/
|
||||||
|
async function openFileMenu() {
|
||||||
|
info("Opening file menu");
|
||||||
|
let fileMenu = document.getElementById("file-menu");
|
||||||
|
let openFileMenuPromise = BrowserTestUtils.waitForPopupEvent(
|
||||||
|
fileMenu,
|
||||||
|
"shown"
|
||||||
|
);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(fileMenu, {});
|
||||||
|
await openFileMenuPromise;
|
||||||
|
return fileMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openAndCloseFileMenu() {
|
||||||
|
await openFileMenu();
|
||||||
|
await EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||||
|
info("Closed file menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for opening toolbar context menu.
|
||||||
|
*/
|
||||||
|
async function openToolbarContextMenu(contextMenu, target) {
|
||||||
|
let popupshown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
|
||||||
|
EventUtils.synthesizeMouseAtCenter(target, { type: "contextmenu" });
|
||||||
|
await popupshown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to paste from clipboard
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function pasteFromClipboard(browser) {
|
||||||
|
return SpecialPowers.spawn(browser, [], () => {
|
||||||
|
let { document } = content;
|
||||||
|
document.body.contentEditable = true;
|
||||||
|
document.body.focus();
|
||||||
|
let pastePromise = new Promise(resolve => {
|
||||||
|
document.addEventListener(
|
||||||
|
"paste",
|
||||||
|
e => {
|
||||||
|
resolve(e.clipboardData.getData("text/plain"));
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
document.execCommand("paste");
|
||||||
|
return pastePromise;
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user