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:
@@ -64,6 +64,12 @@
|
|||||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
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
|
// We take over setting the document title, so remove the l10n id to
|
||||||
// avoid it being re-translated and overwriting document content if
|
// avoid it being re-translated and overwriting document content if
|
||||||
@@ -6734,12 +6740,20 @@ var TabContextMenu = {
|
|||||||
document.getElementById("context_reopenInContainer").hidden =
|
document.getElementById("context_reopenInContainer").hidden =
|
||||||
!Services.prefs.getBoolPref("privacy.userContext.enabled", false) ||
|
!Services.prefs.getBoolPref("privacy.userContext.enabled", false) ||
|
||||||
PrivateBrowsingUtils.isWindowPrivate(window);
|
PrivateBrowsingUtils.isWindowPrivate(window);
|
||||||
|
|
||||||
|
this.updateShareURLMenuItem();
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEvent(aEvent) {
|
handleEvent(aEvent) {
|
||||||
switch (aEvent.type) {
|
switch (aEvent.type) {
|
||||||
|
case "command":
|
||||||
|
this.onShareURLCommand(aEvent);
|
||||||
|
break;
|
||||||
case "popuphiding":
|
case "popuphiding":
|
||||||
gBrowser.removeEventListener("TabAttrModified", this);
|
this.onPopupHiding(aEvent);
|
||||||
aEvent.target.removeEventListener("popuphiding", this);
|
break;
|
||||||
|
case "popupshowing":
|
||||||
|
this.onPopupShowing(aEvent);
|
||||||
break;
|
break;
|
||||||
case "TabAttrModified":
|
case "TabAttrModified":
|
||||||
let tab = aEvent.target;
|
let tab = aEvent.target;
|
||||||
@@ -6749,6 +6763,30 @@ var TabContextMenu = {
|
|||||||
break;
|
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) {
|
createReopenInContainerMenu(event) {
|
||||||
createUserContextMenu(event, {
|
createUserContextMenu(event, {
|
||||||
isContextMenu: true,
|
isContextMenu: true,
|
||||||
@@ -6836,4 +6874,134 @@ var TabContextMenu = {
|
|||||||
gBrowser.removeTab(this.contextTab, { animate: true });
|
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();
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ move-to-new-window =
|
|||||||
tab-context-close-multiple-tabs =
|
tab-context-close-multiple-tabs =
|
||||||
.label = Close Multiple Tabs
|
.label = Close Multiple Tabs
|
||||||
.accesskey = M
|
.accesskey = M
|
||||||
|
tab-context-share-url =
|
||||||
|
.label = Share
|
||||||
|
.accesskey = h
|
||||||
|
tab-context-share-more =
|
||||||
|
.label = More…
|
||||||
|
|
||||||
## Variables:
|
## Variables:
|
||||||
## $tabCount (Number): the number of tabs that are affected by the action.
|
## $tabCount (Number): the number of tabs that are affected by the action.
|
||||||
|
|||||||
@@ -155,6 +155,28 @@ var BrowserUtils = {
|
|||||||
Services.obs.addObserver(observer, topic);
|
Services.obs.addObserver(observer, topic);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isShareableURL(url) {
|
||||||
|
if (!url) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disallow sharing URLs with more than 65535 characters.
|
||||||
|
if (url.spec.length > 65535) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let scheme = url.scheme;
|
||||||
|
|
||||||
|
return !(
|
||||||
|
"about" == scheme ||
|
||||||
|
"resource" == scheme ||
|
||||||
|
"chrome" == scheme ||
|
||||||
|
"wyciwyg" == scheme ||
|
||||||
|
"blob" == scheme ||
|
||||||
|
"moz-extension" == scheme
|
||||||
|
);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(
|
XPCOMUtils.defineLazyPreferenceGetter(
|
||||||
|
|||||||
Reference in New Issue
Block a user