Bug 1690569 - Add Share item to the tab context menu on Windows and macOS. r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D104558
This commit is contained in:
Micah Tigley
2021-02-25 02:51:03 +00:00
parent d7b0e712a0
commit e25e40fd9d
3 changed files with 197 additions and 2 deletions

View File

@@ -64,6 +64,12 @@
XPCOMUtils.defineLazyModuleGetters(this, {
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
});
XPCOMUtils.defineLazyServiceGetters(this, {
MacSharingService: [
"@mozilla.org/widget/macsharingservice;1",
"nsIMacSharingService",
],
});
// We take over setting the document title, so remove the l10n id to
// avoid it being re-translated and overwriting document content if
@@ -6734,12 +6740,20 @@ var TabContextMenu = {
document.getElementById("context_reopenInContainer").hidden =
!Services.prefs.getBoolPref("privacy.userContext.enabled", false) ||
PrivateBrowsingUtils.isWindowPrivate(window);
this.updateShareURLMenuItem();
},
handleEvent(aEvent) {
switch (aEvent.type) {
case "command":
this.onShareURLCommand(aEvent);
break;
case "popuphiding":
gBrowser.removeEventListener("TabAttrModified", this);
aEvent.target.removeEventListener("popuphiding", this);
this.onPopupHiding(aEvent);
break;
case "popupshowing":
this.onPopupShowing(aEvent);
break;
case "TabAttrModified":
let tab = aEvent.target;
@@ -6749,6 +6763,30 @@ var TabContextMenu = {
break;
}
},
onPopupHiding(event) {
// We don't want to rebuild the contents of the "Share" menupopup if only its submenu is
// hidden. So only clear its "data-initialized" attribute when the main context menu is
// hidden.
if (event.target.id === "tabContextMenu") {
let menupopup = document.getElementById("context_shareTabURL_popup");
menupopup?.removeAttribute("data-initialized");
}
gBrowser.removeEventListener("TabAttrModified", this);
event.target.removeEventListener("popuphiding", this);
},
onPopupShowing(event) {
let menupopup = document.getElementById("context_shareTabURL_popup");
if (
event.target === menupopup &&
!menupopup.hasAttribute("data-initialized")
) {
this.initializeShareURLPopup();
}
},
createReopenInContainerMenu(event) {
createUserContextMenu(event, {
isContextMenu: true,
@@ -6836,4 +6874,134 @@ var TabContextMenu = {
gBrowser.removeTab(this.contextTab, { animate: true });
}
},
updateShareURLMenuItem() {
// We don't show a "share URL" in Linux, so bail.
if (!gProton || AppConstants.platform == "linux") {
return;
}
let shareURL = document.getElementById("context_shareTabURL");
if (!shareURL) {
shareURL = this.createShareURLMenuItem();
}
// Don't show the menuitem on non-shareable URLs.
let browser = this.contextTab.linkedBrowser;
shareURL.hidden = !BrowserUtils.isShareableURL(browser.currentURI);
},
/**
* Creates and returns the "Share" menu item.
*/
createShareURLMenuItem() {
let menu = document.getElementById("tabContextMenu");
let shareURL = null;
if (AppConstants.platform == "win") {
shareURL = this.buildShareURLItem();
} else if (AppConstants.platform == "macosx") {
shareURL = this.buildShareURLMenu();
}
let sendTabContext = document.getElementById("context_sendTabToDevice");
menu.insertBefore(shareURL, sendTabContext.nextSibling);
return shareURL;
},
/**
* Returns a menu item specifically for accessing Windows sharing services.
*/
buildShareURLItem() {
let shareURLMenuItem = document.createXULElement("menuitem");
shareURLMenuItem.setAttribute("id", "context_shareTabURL");
document.l10n.setAttributes(shareURLMenuItem, "tab-context-share-url");
shareURLMenuItem.addEventListener("command", this);
return shareURLMenuItem;
},
/**
* Returns a menu specifically for accessing macOSx sharing services .
*/
buildShareURLMenu() {
let menu = document.createXULElement("menu");
menu.id = "context_shareTabURL";
document.l10n.setAttributes(menu, "tab-context-share-url");
let menuPopup = document.createXULElement("menupopup");
menuPopup.id = "context_shareTabURL_popup";
menuPopup.addEventListener("popupshowing", this);
menu.appendChild(menuPopup);
return menu;
},
/**
* Populates the "Share" menupopup on macOSx.
*/
initializeShareURLPopup() {
if (AppConstants.platform !== "macosx") {
return;
}
let menuPopup = document.getElementById("context_shareTabURL_popup");
// Empty menupopup
while (menuPopup.firstChild) {
menuPopup.firstChild.remove();
}
let url = this.contextTab.linkedBrowser.currentURI;
let sharingService = gBrowser.MacSharingService;
let currentURI = gURLBar.makeURIReadable(url).displaySpec;
let services = sharingService.getSharingProviders(currentURI);
services.forEach(share => {
let item = document.createXULElement("menuitem");
item.classList.add("menuitem-iconic");
item.setAttribute("label", share.menuItemTitle);
item.setAttribute("share-name", share.name);
item.setAttribute("image", share.image);
menuPopup.appendChild(item);
});
let moreItem = document.createXULElement("menuitem");
document.l10n.setAttributes(moreItem, "tab-context-share-more");
moreItem.classList.add("menuitem-iconic", "share-more-button");
menuPopup.appendChild(moreItem);
menuPopup.addEventListener("command", this);
menuPopup.setAttribute("data-initialized", true);
},
onShareURLCommand(event) {
// Only call sharing services for the "Share" context menu item. These
// services are accessed from a submenu popup for MacOS or the "Share"
// menu item for Windows.
if (
event.target.parentNode.id !== "context_shareTabURL_popup" &&
event.target.id !== "context_shareTabURL"
) {
return;
}
let browser = this.contextTab.linkedBrowser;
let currentURI = gURLBar.makeURIReadable(browser.currentURI).displaySpec;
if (AppConstants.platform == "win") {
WindowsUIUtils.shareUrl(currentURI, browser.contentTitle);
return;
}
// On macOSX platforms
let sharingService = gBrowser.MacSharingService;
let shareName = event.target.getAttribute("share-name");
if (shareName) {
sharingService.shareUrl(shareName, currentURI, browser.contentTitle);
} else if (event.target.classList.contains("share-more-button")) {
sharingService.openSharingPreferences();
}
},
};